Introducción: ¿por qué su formulario Angular grita un error?
\n¿Alguna vez se ha encontrado con esta situación: escribe un formulario hermoso en Angular Material, todo parece perfecto, pero la consola del navegador de repente muestra el mensaje:
\nmat-form-field must contain a MatFormFieldControl\nO, si usa el modo estricto de TypeScript, puede aparecer algo como:
\nError: mat-form-field must contain a MatFormFieldControl. Did you forget to add a directive that implements MatFormFieldControl?\nEste es uno de los errores más populares en Stack Overflow (¡miles de visitas!), y hoy lo analizaremos de arriba a abajo. Aprenderá no solo cómo solucionar este problema, sino también por qué ocurre. Y lo más importante: aprenderá a crear sus propios controles para Angular Material, si el estándar MatInput no se adapta a sus necesidades.
¡Allá vamos! 🚀
\n\n¿Qué es MatFormFieldControl y para qué sirve?
\nAntes de curar el error, entendamos la anatomía de Angular Material. mat-form-field es un contenedor que agrega la estilización de Material Design (etiqueta, subrayado, sugerencias, errores). Pero por sí mismo no muestra nada. Necesita un "hijo": una directiva o componente que implemente la interfaz MatFormFieldControl.
Esta interfaz (o clase abstracta) describe cómo el control interactúa con el formulario: cómo obtener el valor, cómo mostrar un error, cómo manejar el foco. La implementación estándar es MatInput. Si escribe:
<mat-form-field>\n <input matInput placeholder="Nombre">\n</mat-form-field>\n— la directiva matInput implementa automáticamente MatFormFieldControl.
El error ocurre cuando Angular no encuentra ningún elemento hijo con dicha implementación. Por ejemplo:
\n<mat-form-field>\n <input placeholder="Nombre"> <!-- ¡Sin matInput! -->\n</mat-form-field>\nO cuando intenta usar un componente personalizado que no ha conectado la interfaz.
\n\nCausas típicas del error (y cómo solucionarlas)
\n\n1. Olvidó agregar la directiva matInput
\nLa causa más simple. Simplemente no especificó matInput en el elemento <input>.
Incorrecto:
\n<mat-form-field>\n <input placeholder="Email">\n</mat-form-field>\nCorrecto:
\n<mat-form-field>\n <input matInput placeholder="Email">\n</mat-form-field>\nVerifique también que haya importado MatInputModule en su módulo:
import { MatInputModule } from '@angular/material/input';\n\n@NgModule({\n imports: [MatInputModule]\n})\nexport class AppModule { }\n\n2. Usa el elemento HTML incorrecto
\nMatInput solo funciona con <input> y <textarea>. Si intenta envolver en mat-form-field un <div> común o un <select> (sin mat-select), obtendrá el error.
Incorrecto:
\n<mat-form-field>\n <div>Algún contenido</div>\n</mat-form-field>\nCorrecto: use los componentes Material correspondientes:
\n<mat-form-field>\n <mat-select placeholder="Ciudad">\n <mat-option value="1">Madrid</mat-option>\n </mat-select>\n</mat-form-field>\nPara mat-select necesita importar MatSelectModule.
3. El componente personalizado no implementa MatFormFieldControl
\nEste es un caso más complejo. Supongamos que creó su propio componente para ingresar una fecha o una calificación. Angular Material no lo conoce. Es necesario "enseñarle" explícitamente.
\n