Introduction : pourquoi votre formulaire Angular crie-t-il une erreur ?
\nAvez-vous déjà rencontré cette situation : vous écrivez un beau formulaire avec Angular Material, tout semble parfait, mais soudain la console du navigateur affiche le message :
\nmat-form-field must contain a MatFormFieldControl\nOu, si vous utilisez le mode strict de TypeScript, quelque chose comme :
\nError: mat-form-field must contain a MatFormFieldControl. Did you forget to add a directive that implements MatFormFieldControl?\nC'est l'une des erreurs les plus populaires sur Stack Overflow (des milliers de vues !), et aujourd'hui nous allons l'analyser en profondeur. Vous apprendrez non seulement comment corriger ce problème, mais aussi pourquoi il se produit. Et surtout, vous apprendrez à créer vos propres contrôles pour Angular Material si le MatInput standard ne vous convient pas.
C'est parti ! 🚀
\n\nQu'est-ce que MatFormFieldControl et à quoi sert-il ?
\nAvant de traiter l'erreur, comprenons l'anatomie d'Angular Material. mat-form-field est un conteneur qui ajoute le style Material Design (label, soulignement, indices, erreurs). Mais à lui seul, il n'affiche rien. Il a besoin d'un "enfant" — une directive ou un composant qui implémente l'interface MatFormFieldControl.
Cette interface (ou classe abstraite) décrit comment le contrôle interagit avec le formulaire : comment obtenir la valeur, comment afficher une erreur, comment gérer le focus. L'implémentation standard est MatInput. Si vous écrivez :
<mat-form-field>\n <input matInput placeholder="Nom">\n</mat-form-field>\n— alors la directive matInput implémente automatiquement MatFormFieldControl.
L'erreur se produit lorsque Angular ne trouve aucun élément enfant avec une telle implémentation. Par exemple :
\n<mat-form-field>\n <input placeholder="Nom"> <!-- Pas de matInput ! -->\n</mat-form-field>\nOu lorsque vous essayez d'utiliser un composant personnalisé qui n'a pas connecté l'interface.
\n\nCauses typiques de l'erreur (et comment les corriger)
\n\n1. Vous avez oublié d'ajouter la directive matInput
\nLa cause la plus banale. Vous n'avez tout simplement pas spécifié matInput sur l'élément <input>.
Incorrect :
\n<mat-form-field>\n <input placeholder="Email">\n</mat-form-field>\nCorrect :
\n<mat-form-field>\n <input matInput placeholder="Email">\n</mat-form-field>\nVérifiez également que vous avez importé MatInputModule dans votre module :
import { MatInputModule } from '@angular/material/input';\n\n@NgModule({\n imports: [MatInputModule]\n})\nexport class AppModule { }\n\n2. Vous utilisez le mauvais élément HTML
\nMatInput fonctionne uniquement avec <input> et <textarea>. Si vous essayez d'envelopper un simple <div> ou <select> (sans mat-select) dans mat-form-field, vous obtiendrez une erreur.
Incorrect :
\n<mat-form-field>\n <div>Du contenu quelconque</div>\n</mat-form-field>\nCorrect : utilisez les composants Material appropriés :
\n<mat-form-field>\n <mat-select placeholder="Ville">\n <mat-option value="1">Paris</mat-option>\n </mat-select>\n</mat-form-field>\nPour mat-select, vous devez importer MatSelectModule.
3. Le composant personnalisé n'implémente pas MatFormFieldControl
\nC'est un cas plus complexe. Supposons que vous ayez créé votre propre composant pour la saisie de date ou d'évaluation. Angular Material ne le connaît pas. Vous devez explicitement "lui apprendre".
\n