mat-form-field debe contener un MatFormFieldControl

189

Estamos tratando de construir nuestros propios componentes de campo de formulario en nuestra empresa. Estamos tratando de envolver los componentes del diseño de materiales de esta manera:

campo:

<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>

caja de texto:

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

Uso:

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

Esto da como resultado aproximadamente esto:

    <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>

Pero obtengo "mat-form-field debe contener un MatFormFieldControl" en la consola. Supongo que esto tiene que ver con mat-form-field que no contiene directamente un matInput-field. Pero lo está conteniendo, solo está dentro de la proyección de contenido ng.

Aquí hay un bombardeo: https://stackblitz.com/edit/angular-xpvwzf

Viktor Eriksson
fuente
3
¿Alguna vez resolviste el problema? Tengo exactamente el mismo problema. Las respuestas no son relevantes.
numsu
No, desafortunadamente no :/. Encontré esto: github.com/angular/material2/issues/9411 y si entiendo esto correctamente, este es un cajero automático no compatible.
Viktor Eriksson el
Ok .. Gracias, terminé haciendo un componente que simplemente resume todas las sugerencias y validaciones y lo coloqué debajo del elemento de entrada.
numsu
@ViktorEriksson Si mi respuesta fue útil para usted, ¿le gustaría aceptarla?
darksoulsong
1
Lo siento, pero no fue útil, mi pregunta tiene muy poco que ver con esa respuesta.
Viktor Eriksson

Respuestas:

28

Desafortunadamente, la proyección de contenido en mat-form-field aún no es compatible. Siga el siguiente problema de github para obtener las últimas noticias al respecto.

Por ahora, la única solución para usted es colocar su contenido directamente en el componente mat-form-field o implementar una clase MatFormFieldControl creando así un componente de campo de formulario personalizado.

n.yakovenko
fuente
133
Encontré esta pregunta buscando en Google un mensaje de error. La respuesta a continuación , que indica que MatInputModuledebe importarse, resolvió mi problema. Como esta es la respuesta aceptada, agrego el enlace aquí, con la esperanza de que ahorre tiempo a los demás.
CGFoX
44
Mi problema era que había olvidado importar ' FormsModule '. Espero que esto ayude a alguien.
lerenau
@CGFoX ¡Tienes toda la razón, amigo! ¡importar MatInputModule resolvió mi problema!
Rafique Mohammed
55
También dentro de una <mat-form-field>etiqueta debe asegurarse de agregar correctamente el matInputatributo en cada inputetiqueta o matNativeControlatributo en cada<select>
svassr
1
@CGFoX Desearía que actualizaran la documentación con esta información y mejores ejemplos ...
412

Tuve este problema Importé MatFormFieldModuleen mi módulo principal, pero olvidé agregar MatInputModulea la importsmatriz, así:

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

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

Espero eso ayude.

Más información aquí .

Darksoulsong
fuente
9
También dentro de una <mat-form-field>etiqueta debe asegurarse de agregar correctamente el matInputatributo en cada inputetiqueta o matNativeControlatributo en cada <select>etiqueta
svassr
Gracias. Resuelto mi problema Soy nuevo en material angular. Parece que necesito importar muchos, muchos módulos para usar el material angular. Por ejemplo, necesitamos importar "MatButtonModule" para usar botones, "MatCheckboxModule" para usar casillas de verificación, "MatFormFieldModule" para usar formularios, "MatInputModule" para usar la entrada ... Es realmente agotador. ¿Hay alguna manera de importar solo una o dos veces y luego podríamos comenzar a usar el material angular sin más preocupaciones?
William Hou
1
IMPORTANTE: ¡El orden importa!
Becario Senior
no funciona para mí, acabo de usar este ejemplo: material.angular.io/components/stepper/overview
tatsu
Esto funcionó para mí import { MatInputModule } from '@angular/material/input':
Jared Whipple
86

Solución 1 - importar MatInputModule

importar MatInputModuledentro del módulo, es decirapp.module.ts

Angular 9+

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

Por debajo del angular 9

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

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

Solución 2 - Error de ortografía

Asegúrese de agregar matInputy es sensible a mayúsculas y minúsculas.

<input matInput type="text" />
WasiF
fuente
2
Ahh esto me estaba volviendo loco. La razón uno funcionó para mí. Siento que eso debería especificarse en la documentación, aunque ahora parece obvio.
Fingir
Encontré este problema cuando faltaba "matInput" en la declaración de entrada.
HadidAli
17

Citando de la documentación oficial aquí :

Error: mat-form-field debe contener un MatFormFieldControl

Este error se produce cuando no ha agregado un control de campo de formulario a su campo de formulario. Si su campo de formulario contiene un elemento o elemento nativo, asegúrese de haberle agregado la directiva matInput y haber importado MatInputModule. Otros componentes que pueden actuar como control de campo de formulario incluyen, y cualquier control de campo de formulario personalizado que haya creado.

usuario158
fuente
14

Esto también puede suceder si tiene una entrada adecuada dentro de un campo de formulario mat , pero tiene una entrada ngIf. P.ej:

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

En mi caso, mat-chip-listse supone que "aparece" solo después de cargar sus datos. Sin embargo, la validación se realiza y se mat-form-fieldqueja con

mat-form-field debe contener un MatFormFieldControl

Para solucionarlo, el control debe estar allí, así que he usado [hidden]:

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

Una solución alternativa es propuesta por Mosta: move * ngIf para mat-form-field:

<mat-form-field *ngIf="!_dataLoading">
    <mat-chip-list >
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>
Alexei
fuente
Acabo de tener un problema similar, lo arreglé con algo similar a lo que estás diciendo. Tienes mi voto a favor!
Alex
3
Gracias, en lugar de usar oculto, puede mover la condición ngIf en toda la etiqueta mat-form-field
Mosta
9
import {MatInputModule} from '@angular/material/input';



@NgModule({
    imports: [
        MatInputModule
    ],
    exports: [
        MatInputModule
    ]
})
Ib Abayomi Alli
fuente
3
Bienvenido a stackoverflow. Al responder preguntas, agregue alguna explicación sobre lo que hace su fragmento de código y por qué resuelve la pregunta del OP. Para obtener más información, consulte aquí Cómo responder
Djensen
6

No estoy seguro de si podría ser así de simple, pero tuve el mismo problema, cambiar "mat-input" a "matInput" en el campo de entrada resolvió el problema. En su caso, veo "matinput" y está causando que mi aplicación arroje el mismo error.

<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"

ingrese la descripción de la imagen aquí

"matInput"

ingrese la descripción de la imagen aquí

Tabla de retorno
fuente
hmm no estoy seguro, has pegado la salida generada. En el código real, ya es matInput, si ve "textbox-section". No tengo problemas para que funcione cuando solo uso material, es cuando trato de hacer que mi propio componente con proyección deje de funcionar. Parece que mi saqueador tiene problemas con el cajero automático, espero que se solucione durante el día.
Viktor Eriksson
Oh ya veo, mi mal. Esta fue una posibilidad remota de todos modos. Seguiré para ver si alguien puede llegar al ángulo de inclinación correcto, tengo curiosidad sobre este problema.
VolverTable
2
Sucedió conmigo, me he olvidado de cambiar mdInputa matInput.
Ebraheem Alrabee '
2
Angular 5: el atributo de etiqueta <input> debe ser en matInputlugar de mat-input.
Stavm
6

Si alguien se atascó con este error después de intentar anidar a <mat-checkbox>, ¡anímate! No funciona dentro de una <mat-form-field>etiqueta.

Mina
fuente
6

si alguien está tratando de anidar un <mat-radio-group>interior <mat-form-field> como el siguiente, obtendrá este error

         <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>

eliminar las <mat-form-field>etiquetas principales

Steve sonius
fuente
Estaba teniendo este problema y tenía un fragmento de marcado con este tipo de cosas. Eliminarlo mat-form-fieldhizo que el problema desapareciera para mí.
Andrew Gray
¿Hay alguna razón que <mat-form-field>no sea compatible con el grupo de radio dentro de él? También estaba teniendo este problema y no pensé en eliminar las etiquetas de campo de formulario de estera porque no parecía que fuera lo correcto, ya que se usan muchos materiales de ejemplos de formularios de interfaz de usuario <mat-form-field>. Tengo todos los diversos módulos de entrada de formularios de materiales para formularios, menús desplegables seleccionados y grupos de radio definidos en mi app.module.ts como muchas de las otras referencias de respuestas.
Alex
No puedo creer ... Intento todo y nada para trabajar ... y después de unos días de dolor encontré esta solución tan simple ... gracias amigo
Arter
4

También tuve este problema, y ​​tengo un <mat-select>elemento en mi plantilla, cuando importo el MatSelectModule en el Módulo, funciona, no hace ciencia, pero espero que pueda ayudarlo.

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>
user9001817
fuente
Funciona ya que sin importar el módulo, el control mat-form-field no comprende qué es un mat-select. Cuando se importa, puede corregir toda la información y, por lo tanto, puede analizar la plantilla sin más errores.
PeterS
3

Desafortunadamente, no puedo comentar algunas respuestas ya buenas, ya que todavía no tengo los puntos SO, sin embargo, hay 3 módulos clave que necesitará para asegurarse de que está importando al módulo principal de su componente, aparte de lo que tienes que importar directamente a tu componente. Quería compartirlos brevemente y resaltar lo que hacen.

  1. MatInputModule
  2. MatFormFieldModule
  3. ReactiveFormsModule

Los dos primeros son para material angular. Muchas personas nuevas en Angular Material se encontrarán instintivamente con uno de estos y no se darán cuenta de que construir una forma requiere ambos.

Entonces, ¿cuál es la diferencia entre ellos?

MatFormFieldModule abarca todos los diferentes tipos de campos de formulario que Angular Material tiene disponible. Este es más un módulo de alto nivel para campos de formulario en general, mientras que MatInputModule es específicamente para tipos de campo de 'entrada', en lugar de cuadros de selección, botones de opción, etc.

El tercer elemento en la lista anterior es el Módulo de formularios reactivos de Angular. El módulo de formas reactivas es responsable de una tonelada de amor angular bajo el capó. Si vas a trabajar con Angular, te recomiendo que pases un tiempo leyendo Angular Docs. Tienen todas tus respuestas. La creación de aplicaciones rara vez NO involucra formularios, y la mayoría de las veces, su aplicación incluirá formularios reactivos. Por esa razón, tómese el tiempo de leer estas dos páginas.

Documentos angulares: formas reactivas

Documentos angulares: módulo de formularios reactivos

El primer documento 'Formas reactivas' será su arma más poderosa cuando comience, y el segundo documento será su arma más poderosa a medida que avance en aplicaciones más avanzadas de Formas reactivas angulares.

Recuerde, estos deben importarse directamente en el módulo de su componente, no en el componente en el que los está utilizando. Si no recuerdo mal, en Angular 2, importamos el conjunto completo de módulos de material angular en nuestro módulo de aplicación principal, y luego importamos qué Necesitábamos en cada uno de nuestros componentes directamente. El método actual es una OMI mucho más eficiente porque estamos garantizados para importar el conjunto completo de módulos de material angular si solo usamos algunos de ellos.

Espero que esto proporcione un poco más de información sobre la creación de formas con material angular.

otro codificador
fuente
3

Si todas las respuestas de configuración / estructura del código principal anteriores no resuelven su problema, aquí hay una cosa más que debe verificar: asegúrese de no haber invalidado de alguna manera su <input>etiqueta.

Por ejemplo, recibí el mismo mat-form-field must contain a MatFormFieldControlmensaje de error después de colocar accidentalmente un requiredatributo después de una barra oblicua /, lo que efectivamente invalidó mi <input/>. En otras palabras, hice esto (ver el final de los atributos de la etiqueta de entrada):

mal :

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

derecha :

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

Si comete ese error u otra cosa para invalidar su <input>, entonces podría obtener el mat-form-field must contain a MatFormFieldControlerror. De todos modos, esto es solo una cosa más a tener en cuenta mientras estás depurando.

cjn
fuente
3

El mismo error puede ocurrir si tiene una diapositiva de mat dentro de un campo de mat como el único elemento en mi caso que tuve

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

Esto podría suceder si tuviera varios atributos dentro de la <mat-form-field> solución simple: mover la diapositiva a la raíz

Kisinga
fuente
1
Esto me salvó la vida. Gracias.
Paulo Pedroso
2

Puede intentar seguir esta guía e implementar / proporcionar su propio MatFormFieldControl

rivanov
fuente
2

Accidentalmente eliminé la directiva matInput del campo de entrada que causó el mismo error.

p.ej.

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

código fijo

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

MatRadioModule no funcionará dentro de MatFormField. Los documentos dicen

Este error se produce cuando no ha agregado un control de campo de formulario a su campo de formulario. Si su campo de formulario contiene un elemento o elemento nativo, asegúrese de haberle agregado la directiva matInput y haber importado MatInputModule. Otros componentes que pueden actuar como control de campo de formulario incluyen <mat-select>, <mat-chip-list> y cualquier control de campo de formulario personalizado que haya creado.

intotecho
fuente
2

En mi caso, uno de mis paréntesis de cierre para "onChanges ()" se perdió en el elemento de entrada y, por lo tanto, el elemento de entrada aparentemente no se representaba en absoluto:

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

Una solución parcial es envolver el campo de formulario de material en un componente personalizado e implementar el ControlValueAccessor interfaz en él. Además de la proyección de contenido, el efecto es prácticamente el mismo.

Ver ejemplo completo en Stackblitz.

Usé FormControl( formas reactivas ) dentro CustomInputComponentpero FormGroupoFormArray debería funcionar también si usted necesita un elemento de forma más compleja.

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>
csg
fuente
2

Has perdido la matInput directiva en tu etiqueta de entrada.

Isaac Pitwa
fuente
2

Debe importar MatInputModule en su archivo app.module.ts

importar {MatInputModule} desde '@ 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
  ],
Shashwat Gupta
fuente
2

Puede establecer apariencia = "relleno" dentro de su etiqueta mat-form-field, funciona para mí

<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>
pawan singare
fuente
Esto solucionó mi problema. ¿Puede explicar qué appearence = "fill"está haciendo aquí?
IamGrooot
2

Angular 9+ ... Material 9+

He notado que 3 errores pueden dar lugar al mismo error:

  1. Asegúrese de haber importado MatFormFieldModule y MatInputModule en app.module o module.ts donde se importan sus componentes (en el caso de módulos anidados)
  2. Cuando envuelve botones de material o casillas de verificación en mat-form-field. Consulte la lista de componentes de material que se pueden envolver con mat-form-field mat-form-field
  3. Cuando no puede incluir matInput en su etiqueta. es decir, <input matInput type = "number" step = "0.01" formControlName = "price" />
7guyo
fuente
2

La nueva importación actualizada del módulo MatInput es:

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

Según la API de materiales angulares

SaiSurya
fuente
1

En mi caso cambié esto:

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

a esto:

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

Agregar la directiva matInput a la etiqueta de entrada fue lo que solucionó este error para mí.

Gilmourguru
fuente
1

Es posible que no haya importado MatInputModule

Pranith Baggan
fuente
1

usar proveedores en el archivo component.ts

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

Nota En algún momento se produce un error, cuando usamos la etiqueta "mat-form-field" alrededor del botón de envío como:

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

Así que amablemente no use esta etiqueta alrededor del botón Enviar

Abdullah
fuente
0

Tuve el mismo problema

el problema es simple

solo debes importar dos módulos a tu proyecto

MatFormFieldModule MatInputModule

Fatih Çakıroğlu
fuente
0

Estaba recibiendo el mismo problema debido al elemento comentado de la siguiente manera.

<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>

¡El campo de formulario debe tener elemento! (por ejemplo, la entrada, el área de texto, select, etc.)

U_R_Naveen UR_Naveen
fuente