mat-form-field doit contenir un MatFormFieldControl


190

Nous essayons de construire nos propres composants de champ de formulaire dans notre entreprise. Nous essayons d'envelopper les composants de la conception matérielle comme ceci:

champ:

<mat-form-field>
    <ng-content></ng-content>
    <mat-hint align="start"><strong>{{hint}}</strong> </mat-hint>
    <mat-hint align="end">{{message.value.length}} / 256</mat-hint>
    <mat-error>This field is required</mat-error>
</mat-form-field>

zone de texte:

<field hint="hint">
    <input matInput 
    [placeholder]="placeholder" 
    [value]="value"
    (change)="onChange($event)" 
    (keydown)="onKeydown($event)" 
    (keyup)="onKeyup($event)" 
    (keypress)="onKeypress($event)">
</field>

Usage:

<textbox value="test" hint="my hint"></textbox>

Il en résulte à peu près ceci:

    <textbox  placeholder="Personnummer/samordningsnummer" value="" ng-reflect-placeholder="Personnummer/samordningsnummer">
       <field>
          <mat-form-field class="mat-input-container mat-form-field>
             <div class="mat-input-wrapper mat-form-field-wrapper">
                <div class="mat-input-flex mat-form-field-flex">
                   <div class="mat-input-infix mat-form-field-infix">
                      <input _ngcontent-c4="" class="mat-input-element mat-form-field-autofill-control" matinput="" ng-reflect-placeholder="Personnummer/samordningsnummer" ng-reflect-value="" id="mat-input-2" placeholder="Personnummer/samordningsnummer" aria-invalid="false">
                      <span class="mat-input-placeholder-wrapper mat-form-field-placeholder-wrapper"></span>
                   </div>
                </div>
                <div class="mat-input-underline mat-form-field-underline">
                   <span class="mat-input-ripple mat-form-field-ripple"></span>
                </div>
                <div class="mat-input-subscript-wrapper mat-form-field-subscript-wrapper"></div>
             </div>
          </mat-form-field>
       </field>
    </textbox>

Mais j'obtiens "mat-form-field doit contenir un MatFormFieldControl" dans la console. Je suppose que cela a à voir avec mat-form-field ne contenant pas directement un matInput-field. Mais il le contient, c'est juste avec la projection ng-content.

Voici un blitz: https://stackblitz.com/edit/angular-xpvwzf


3
Avez-vous déjà résolu le problème? J'ai exactement le même problème. Les réponses ne sont pas pertinentes.
numsu

Non, malheureusement non :/. J'ai trouvé ceci: github.com/angular/material2/issues/9411 et si je comprends bien cela, ce atm n'est pas pris en charge.
Viktor Eriksson

Ok .. Merci, j'ai fini par créer un composant qui englobe tous les conseils et validations et le place sous l'élément d'entrée.
numsu

@ViktorEriksson Si ma réponse vous a été utile, voulez-vous l'accepter?
darksoulsong

1
Je suis désolé mais ce n'était pas utile, ma question a très peu à voir avec cette réponse.
Viktor Eriksson

Réponses:


28

Malheureusement, la projection de contenu dans le champ mat-form-field n'est pas encore prise en charge. Veuillez suivre le problème github suivant pour obtenir les dernières nouvelles à ce sujet.

À présent, la seule solution pour vous est de placer votre contenu directement dans le composant mat-form-field ou d'implémenter une classe MatFormFieldControl créant ainsi un composant de champ de formulaire personnalisé.


133
Je suis tombé sur cette question en recherchant un message d'erreur sur Google. La réponse ci - dessous , indiquant qu'il MatInputModulefaut importer, a résolu mon problème. Comme c'est la réponse acceptée, j'ajoute le lien ici, en espérant que cela fera gagner du temps aux autres.
CGFoX

4
Mon problème était que j'avais négligé d'importer « FormsModule ». J'espère que ça aidera quelqu'un.
lerenau

@CGFoX Vous avez absolument raison mec !! l'importation de MatInputModule a résolu mon problème !!
Rafique Mohammed

5
Aussi à l'intérieur d'une <mat-form-field>balise, vous devez vous assurer que vous avez correctement ajouté un matInputattribut sur chaque inputbalise ou ou matNativeControlattribut sur chaque<select>
svassr

1
@CGFoX Je souhaite qu'ils mettent à jour la documentation avec ces informations et de meilleurs exemples ...

413

J'ai eu ce problème. J'ai importé MatFormFieldModuledans mon module principal, mais j'ai oublié d'ajouter MatInputModuleau importstableau, comme ceci:

import { MatFormFieldModule, MatInputModule } from '@angular/material';

@NgModule({
    imports: [
        MatFormFieldModule,
        MatInputModule
    ]
})
export class AppModule { }

J'espère que ça aide.

Plus d'infos ici .


9
Aussi à l'intérieur d'une <mat-form-field>balise, vous devez vous assurer que vous avez correctement ajouté un matInputattribut sur chaque inputbalise ou ou matNativeControlattribut sur chaque <select>balise
svassr

Je vous remercie. J'ai résolu mon problème. Je suis nouveau sur Angular Material. Il semble que j'ai besoin d'importer de très nombreux modules pour utiliser Angular Material. Par exemple, nous devons importer "MatButtonModule" pour utiliser les boutons, "MatCheckboxModule" pour utiliser les cases à cocher, "MatFormFieldModule" pour utiliser les formulaires, "MatInputModule" pour utiliser l'entrée ... C'est vraiment fatiguant. Y a-t-il un moyen d'importer juste une ou deux fois et ensuite nous pourrions commencer à utiliser Angular Material sans plus de soucis?
William Hou

1
IMPORTANT: la commande compte!
Becario Senior

ne fonctionne pas pour moi, je viens d'utiliser cet exemple: material.angular.io/components/stepper/overview
tatsu

Cela a fonctionné pour moi import { MatInputModule } from '@angular/material/input':
Jared Whipple le

86

Solution 1 - Importer MatInputModule

importer à l' MatInputModuleintérieur du module ieapp.module.ts

Angulaire 9+

import { MatInputModule } from '@angular/material/input';

Ci-dessous angulaire 9

import { MatInputModule } from '@angular/material';

@NgModule({
  imports: [
     // .......
     MatInputModule
     // .......
  ]
})
export class AppModule { }

Solution 2 - Erreur d'orthographe

Assurez-vous d'ajouter matInputet il est sensible à la casse.

<input matInput type="text" />

2
Ahh ça me rendait fou. La première raison a fonctionné pour moi. Je pense que cela devrait être spécifié dans la documentation, même si cela semble évident maintenant.
Feign le

J'ai rencontré ce problème lorsque "matInput" était absent de l'instruction d'entrée.
HadidAli le

17

Citant la documentation officielle ici :

Erreur: mat-form-field doit contenir un MatFormFieldControl

Cette erreur se produit lorsque vous n'avez pas ajouté de contrôle de champ de formulaire à votre champ de formulaire. Si votre champ de formulaire contient un élément natif ou un élément, assurez-vous que vous y avez ajouté la directive matInput et que vous avez importé MatInputModule. Les autres composants pouvant servir de contrôle de champ de formulaire incluent, et tous les contrôles de champ de formulaire personnalisés que vous avez créés.


14

Cela peut également se produire si vous avez une entrée correcte dans un champ mat-form-field , mais il en a un ngIf. Par exemple:

<mat-form-field>
    <mat-chip-list *ngIf="!_dataLoading">
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>

Dans mon cas, mat-chip-listest censé "apparaître" uniquement après le chargement de ses données. Cependant, la validation est effectuée et se mat-form-fieldplaint de

mat-form-field doit contenir un MatFormFieldControl

Pour le réparer, le contrôle doit être là, j'ai donc utilisé [hidden]:

<mat-form-field>
    <mat-chip-list [hidden]="_dataLoading">
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>

Une solution alternative est proposée par Mosta: move * ngIf pour mat-form-field:

<mat-form-field *ngIf="!_dataLoading">
    <mat-chip-list >
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>

J'ai juste eu un problème similaire, je l'ai résolu avec quelque chose de similaire à ce que vous dites. Vous avez mon vote positif!
Alex

3
Merci, au lieu d'utiliser hidden, vous pouvez déplacer la condition ngIf sur toute la balise mat-form-field
Mosta

9
import {MatInputModule} from '@angular/material/input';



@NgModule({
    imports: [
        MatInputModule
    ],
    exports: [
        MatInputModule
    ]
})

3
Bienvenue dans stackoverflow. Lorsque vous répondez aux questions, veuillez ajouter des explications sur ce que fait votre extrait de code et pourquoi il résout la question du PO. Pour plus d'informations, consultez ici Comment répondre
Djensen

6

Je ne suis pas sûr que cela puisse être aussi simple mais j'ai eu le même problème, changer "mat-input" en "matInput" dans le champ de saisie a résolu le problème. Dans votre cas, je vois "matinput" et mon application génère la même erreur.

<input _ngcontent-c4="" class="mat-input-element mat-form-field-autofill-control" matinput="" ng-reflect-placeholder="Personnummer/samordningsnummer" ng-reflect-value="" id="mat-input-2" placeholder="Personnummer/samordningsnummer" aria-invalid="false">

"matinput"

entrez la description de l'image ici

"matInput"

entrez la description de l'image ici


hmm pas sûr, vous avez collé la sortie générée. Dans le vrai code, c'est déjà matInput, si vous voyez "textbox-section". Je n'ai aucun problème à le faire fonctionner lorsque je n'utilise que du matériel, c'est en essayant de créer mon propre composant avec la projection, il cesse de fonctionner. Mon plunker semble avoir des problèmes ATM, j'espère qu'il se résoudra pendant la journée.
Viktor Eriksson

Oh je vois, mon mal. C'était un long coup de toute façon. Je vais suivre pour voir si quelqu'un peut réellement trouver le bon angle d'inclinaison, je suis curieux de connaître ce problème.
Table de retour du

2
Il est arrivé avec moi, je l' ai oublié de changement mdInputà matInput.
Ebraheem Alrabee '

2
Angulaire 5: l'attribut de balise <input> doit être à la matInputplace de mat-input.
Stavm

6

Si quelqu'un est resté coincé avec cette erreur après avoir tenté d'imbriquer un <mat-checkbox>, soyez de bonne humeur! Cela ne fonctionne pas à l'intérieur d'une <mat-form-field>balise.


6

si quelqu'un essaie d'imbriquer un <mat-radio-group>intérieur <mat-form-field> comme ci-dessous, vous obtiendrez cette erreur

         <mat-form-field>
                <!-- <mat-label>Image Position</mat-label> -->
                <mat-radio-group aria-label="Image Position" [(ngModel)]="section.field_1">
                    <mat-radio-button value="left">Left</mat-radio-button>
                    <mat-radio-button value="right">Right</mat-radio-button>
                </mat-radio-group>
            </mat-form-field>

supprimer les <mat-form-field>balises parentes


J'avais ce problème et j'avais un extrait de balisage avec ce genre de chose. En supprimant le, mat-form-fieldle problème a disparu pour moi.
Andrew Gray

Y a-t-il une raison qui <mat-form-field>ne supporte pas le groupe radio à l'intérieur? J'avais également ce problème et je ne pensais pas simplement supprimer les balises de champ de formulaire de tapis, car cela ne semblait pas être la bonne chose à faire car de nombreux exemples de formulaires d'interface utilisateur de matériaux utilisent <mat-form-field>. J'ai tous les différents modules d'entrée de formulaire pour les formulaires, sélectionnez les listes déroulantes et les groupes de radio définis dans mon app.module.ts comme beaucoup d'autres références de réponses.
Alex

Je ne peux pas le croire .... j'essaye tout et rien pour marcher .... et après quelques jours de douleur j'ai trouvé cette solution si simple ... merci
mec

4

J'ai eu ce problème aussi, et j'ai un <mat-select>élément dans mon modèle, lorsque j'importe le MatSelectModule dans Module, cela fonctionne, cela ne fait pas de science, mais j'espère toujours que cela pourra vous aider.

import { MatSelectModule } from '@angular/material/select';

imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MatSidenavModule,
    MatButtonModule,
    MatIconModule,
    MatToolbarModule,
    MatFormFieldModule,
    MatProgressSpinnerModule,
    MatInputModule,
    MatCardModule,
    MatSelectModule
],

<div class="example-container">
    <mat-form-field>
        <input matInput placeholder="Input">
    </mat-form-field>

    <mat-form-field>
        <textarea matInput placeholder="Textarea"></textarea>
    </mat-form-field>

    <mat-form-field>
        <mat-select placeholder="Select">
            <mat-option value="option">Option</mat-option>
        </mat-select>
    </mat-form-field>
</div>

Cela fonctionne comme sans importer le module, le contrôle mat-form-field ne comprend pas ce qu'est un mat-select. Lorsqu'il est importé, il peut corriger toutes les informations et peut donc analyser le modèle sans autre erreur.
PeterS

3

Malheureusement, je ne peux pas me contenter de commenter certaines réponses déjà bonnes car je n'ai pas encore les points SO, cependant, il y a 3 modules clés dont vous aurez besoin pour vous assurer que vous importez dans le module parent de votre composant, en plus de ce vous devez importer directement dans votre composant. Je voulais les partager brièvement et souligner ce qu'ils font.

  1. MatInputModule
  2. MatFormFieldModule
  3. ReactiveFormsModule

Les deux premiers sont pour le matériau angulaire. Beaucoup de personnes qui découvrent Angular Material en rencontrent instinctivement un et ne réalisent pas que la construction d'un formulaire nécessite les deux.

Alors, quelle est la différence entre eux?

MatFormFieldModule englobe tous les différents types de champs de formulaire disponibles dans Angular Material. Il s'agit davantage d'un module de haut niveau pour les champs de formulaire en général, alors que le MatInputModule est spécifiquement pour les types de champs `` d'entrée '', par opposition aux boîtes de sélection, aux boutons radio, etc.

Le troisième élément de la liste ci-dessus est le module de formulaires réactifs d'Angular. Le module de formes réactives est responsable d'une tonne d'amour angulaire sous le capot. Si vous allez travailler avec Angular, je vous recommande vivement de passer du temps à lire Angular Docs. Ils ont toutes vos réponses. La création d'applications n'implique que rarement des formulaires et, le plus souvent, votre application impliquera des formulaires réactifs. Pour cette raison, veuillez prendre le temps de lire ces deux pages.

Docs angulaires: formulaires réactifs

Docs angulaires: module de formulaires réactifs

Le premier document «Formulaires réactifs» sera votre arme la plus puissante lorsque vous démarrez, et le deuxième document sera votre arme la plus puissante à mesure que vous passerez à des applications plus avancées de formes réactives angulaires.

N'oubliez pas que ceux-ci doivent être importés directement dans le module de votre composant, pas dans le composant dans lequel vous les utilisez. Si je me souviens bien, dans Angular 2, nous avons importé l'ensemble des modules Angular Material dans notre module d'application principal, puis importé ce nous avions besoin directement dans chacun de nos composants. La méthode actuelle est beaucoup plus efficace IMO car nous sommes assurés d'importer l'ensemble complet des modules de matériau angulaire si nous n'en utilisons que quelques-uns.

J'espère que cela vous donnera un peu plus d'informations sur la construction de formes avec Angular Material.


3

Si toutes les réponses à la structure / configuration du code principal ci-dessus ne résolvent pas votre problème, voici une dernière chose à vérifier: assurez-vous que vous n'avez pas invalidé votre <input> balise d' .

Par exemple, j'ai reçu le même mat-form-field must contain a MatFormFieldControlmessage d'erreur après avoir accidentellement placé un requiredattribut après une barre oblique à fermeture automatique /, ce qui a effectivement invalidé mon <input/>. En d'autres termes, j'ai fait ceci (voir la fin des attributs de balise d'entrée):

faux :

<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" /required>

à droite :

<input matInput type="text" name="linkUrl" [formControl]="listingForm.controls['linkUrl']" required/>

Si vous faites cette erreur ou quelque chose d'autre pour invalider votre <input>, vous pourriez obtenir l' mat-form-field must contain a MatFormFieldControlerreur. Quoi qu'il en soit, ce n'est qu'une dernière chose à rechercher lors du débogage.


3

La même erreur peut se produire si vous avez une diapositive de tapis dans un tapis du champ comme seul élément dans mon cas que j'avais

 <mat-form-field>
    <mat-slide-toggle [(ngModel)]="myvar">
       Some Text
     </mat-slide-toggle>
 </mat-form-field>

Cela peut se produire si vous aviez plusieurs attributs dans la <mat-form-field> solution Simple pour déplacer la bascule de la diapositive à la racine


1
Cela m'a sauvé la vie. Merci.
Paulo Pedroso

2

Vous pouvez essayer de suivre ce guide et implémenter / fournir votre propre MatFormFieldControl


2

J'ai accidentellement retiré le tapis directive du champ de saisie qui a causé la même erreur.

par exemple.

<mat-form-field>
   <input [readOnly]="readOnly" name="amount" formControlName="amount" placeholder="Amount">
</mat-form-field>

code fixe

 <mat-form-field>
   <input matInput [readOnly]="readOnly" name="amount" formControlName="amount" placeholder="Amount">
</mat-form-field>

2

MatRadioModule ne fonctionnera pas dans MatFormField. Les documents disent

Cette erreur se produit lorsque vous n'avez pas ajouté de contrôle de champ de formulaire à votre champ de formulaire. Si votre champ de formulaire contient un élément natif ou un élément, assurez-vous que vous y avez ajouté la directive matInput et que vous avez importé MatInputModule. Les autres composants pouvant servir de contrôle de champ de formulaire incluent <mat-select>, <mat-chip-list> et tous les contrôles de champ de formulaire personnalisés que vous avez créés.


2

Dans mon cas, une de mes parenthèses fermantes pour "onChanges ()" a été manquée sur l'élément d'entrée et donc l'élément d'entrée n'était apparemment pas du tout rendu:

<input mat-menu-item 
      matInput type="text" 
      [formControl]="myFormControl"
      (ngModelChange)="onChanged()>

2

Une solution partielle consiste à envelopper le champ de formulaire matériel dans un composant personnalisé et à y implémenter l' ControlValueAccessorinterface. Outre la projection de contenu, l'effet est à peu près le même.

Voir l' exemple complet sur Stackblitz.

J'ai utilisé des FormControl( formulaires réactifs ) à l'intérieur, CustomInputComponentmais FormGroupou je FormArraydevrais fonctionner aussi si vous avez besoin d'un élément de formulaire plus complexe.

app.component.html

<form [formGroup]="form" (ngSubmit)="onSubmit()">

  <mat-form-field appearance="outline" floatLabel="always" color="primary">
    <mat-label>First name</mat-label>
    <input matInput placeholder="First name" formControlName="firstName" required>
    <mat-hint>Fill in first name.</mat-hint>
    <mat-error *ngIf="firstNameControl.invalid && (firstNameControl.dirty || firstNameControl.touched)">
      <span *ngIf="firstNameControl.hasError('required')">
        You must fill in the first name.
      </span>
    </mat-error>
  </mat-form-field>

  <custom-input
    formControlName="lastName"
    [errorMessages]="errorMessagesForCustomInput"
    [hint]="'Fill in last name.'"
    [label]="'Last name'"
    [isRequired]="true"
    [placeholder]="'Last name'"
    [validators]="validatorsForCustomInput">
  </custom-input>

  <button mat-flat-button
    color="primary"
    type="submit"
    [disabled]="form.invalid || form.pending">
    Submit
  </button>

</form>

custom-input.component.html

<mat-form-field appearance="outline" floatLabel="always" color="primary">
  <mat-label>{{ label }}</mat-label>

  <input
    matInput
    [placeholder]="placeholder"
    [required]="isRequired"
    [formControl]="customControl"
    (blur)="onTouched()"
    (input)="onChange($event.target.value)">
  <mat-hint>{{ hint }}</mat-hint>

  <mat-error *ngIf="customControl.invalid && (customControl.dirty || customControl.touched)">
    <ng-container *ngFor="let error of errorMessages">
    <span *ngFor="let item of error | keyvalue">
      <span *ngIf="customControl.hasError(item.key)">
        {{ item.value }}
      </span>
    </span>
    </ng-container>
  </mat-error>
</mat-form-field>

2

Vous avez manqué une matInput directive dans votre balise d'entrée.


2

Vous devez importer le MatInputModule dans votre fichier app.module.ts

import {MatInputModule} depuis '@ angular / material';

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { CustomerPage } from './components/customer/customer';
import { CustomerDetailsPage } from "./components/customer-details/customer-details";
import { CustomerManagementPageRoutingModule } from './customer-management-routing.module';
import { MatAutocompleteModule } from '@angular/material/autocomplete'
import { ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule} from '@angular/material';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    CustomerManagementPageRoutingModule,
    MatAutocompleteModule,
    MatInputModule,
    ReactiveFormsModule,
    MatFormFieldModule
  ],

2

Vous pouvez définir l'apparence = "fill" dans votre balise mat-form-field, cela fonctionne pour moi

<form class="example-form">
  <mat-form-field class="example-full-width" appearance="fill">
    <mat-label>Username Or Email</mat-label>
    <input matInput placeholder="Username Or Email" type="text">
  </mat-form-field>

  <mat-form-field class="example-full-width" appearance="fill">
    <mat-label>Password</mat-label>
    <input matInput placeholder="Password" type="password">
  </mat-form-field>
</form>

Cela a résolu mon problème. Pouvez-vous s'il vous plaît expliquer ce qui appearence = "fill"se passe ici
IamGrooot

2

Angulaire 9+ ... Matériel 9+

J'ai remarqué que 3 erreurs peuvent donner lieu à la même erreur:

  1. Assurez-vous d'avoir importé MatFormFieldModule et MatInputModule dans l'app.module ou le module.ts où vos composants sont importés (en cas de modules imbriqués)
  2. Lorsque vous enveloppez des boutons de matériau ou une case à cocher dans le champ mat-form-field. Voir la liste des composants de matériau qui peuvent être enveloppés avec mat-form-field mat-form-field
  3. Lorsque vous ne parvenez pas à inclure matInput dans votre balise. ie <input matInput type = "number" step = "0.01" formControlName = "price" />


1

Dans mon cas, j'ai changé ceci:

<mat-form-field>
  <input type="email" placeholder="email" [(ngModel)]="data.email">
</mat-form-field>

pour ça:

<mat-form-field>
  <input matInput type="email" placeholder="email" [(ngModel)]="data.email">
</mat-form-field>

L'ajout de la directive matInput à la balise d'entrée a corrigé cette erreur pour moi.



1

utiliser des fournisseurs dans le fichier component.ts

@Component({
 selector: 'your-selector',
 templateUrl: 'template.html',
 styleUrls: ['style.css'],
 providers: [
 { provide: MatFormFieldControl, useExisting: FormFieldCustomControlExample }   
]
})

0

Remarque Une erreur se produit parfois, lorsque nous utilisons la balise "mat-form-field" autour du bouton d'envoi comme:

<mat-form-field class="example-full-width">
   <button mat-raised-button type="submit" color="primary">  Login</button>
   </mat-form-field>

Alors veuillez ne pas utiliser cette balise autour du bouton d'envoi


0

J'ai eu le même problème

le problème est simple

seulement vous devez importer deux modules dans votre projet

MatFormFieldModule MatInputModule


0

J'obtenais le même problème en raison de l'élément commenté comme suit.

<mat-form-field>
    <mat-label>Database</mat-label>
    <!-- <mat-select>
        <mat-option *ngFor="let q of queries" [value]="q.id">
            {{q.name}}
        </mat-option>
    </mat-select>  -->
</mat-form-field>

Le champ de formulaire doit avoir un élément! (par exemple, l'entrée, la zone de texte, sélectionner, etc.)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.