O campo mat-form-field deve conter um MatFormFieldControl

185

Estamos tentando construir nossos próprios componentes de campo de formulário em nossa empresa. Estamos tentando envolver os componentes do design de material como este:

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>

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

Isso resulta aproximadamente nisso:

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

Mas estou recebendo "mat-form-field deve conter um MatFormFieldControl" no console. Eu acho que isso tem a ver com mat-form-field que não contém diretamente um matInput-field. Mas está contendo, está apenas dentro da projeção de conteúdo ng.

Aqui está uma blitz: https://stackblitz.com/edit/angular-xpvwzf

Viktor Eriksson
fonte
3
Você já resolveu o problema? Estou tendo exatamente o mesmo problema. As respostas não são relevantes.
Numero
Não, infelizmente não :/. Eu encontrei o seguinte: github.com/angular/material2/issues/9411 e se eu entendi corretamente, isso não é suportado.
Viktor Eriksson
Ok .. Obrigado, acabei fazendo um componente que apenas envolve todas as dicas e validações e o coloquei sob o elemento de entrada.
Numero
@ViktorEriksson Se minha resposta foi útil, você aceita aceitá-la?
darksoulsong
1
Sinto muito, mas não foi útil, minha pergunta tem muito pouco a ver com essa resposta.
Viktor Eriksson

Respostas:

27

Infelizmente, a projeção de conteúdo no campo formulário não é ainda suportada. Acompanhe a seguinte edição do github para obter as últimas notícias sobre ela.

Até agora, a única solução para você é colocar seu conteúdo diretamente no componente mat-form-field ou implementar uma classe MatFormFieldControl, criando assim um componente de campo de formulário personalizado.

n.yakovenko
fonte
131
Me deparei com essa pergunta pesquisando uma mensagem de erro no Google. A resposta abaixo , afirmando que MatInputModuleprecisa ser importado, resolveu meu problema. Como essa é a resposta aceita, estou adicionando o link aqui, esperando que ele economize o tempo de outras pessoas.
CGFoX
3
Meu problema era que eu havia negligenciado a importação do ' FormsModule '. Espero que isso ajude alguém.
lerenau 28/09
@CGFoX Você está absolutamente certo, cara !! importar MatInputModule resolveu meu problema !!
Rafique Mohammed
5
Também dentro de uma <mat-form-field>tag que você tem que ter certeza que você adicionou corretamente matInputatributo em cada inputtag ou ou matNativeControlatributo em cada<select>
svassr
1
@CGFoX Eu gostaria que eles atualizar a documentação com esta informação e melhores exemplos ...
409

Eu tive esse problema. Eu importei MatFormFieldModuleno meu módulo principal, mas esqueci de adicionar MatInputModuleà importsmatriz, assim:

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

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

Espero que ajude.

Mais informações aqui .

darksoulsong
fonte
9
Também dentro de uma <mat-form-field>tag que você tem que ter certeza que você adicionou corretamente matInputatributo em cada inputtag ou ou matNativeControlatributo em cada <select>tag
svassr
Obrigado. Resolveu o meu problema. Eu sou novo no Material Angular. Parece que preciso importar muitos, muitos módulos para usar o Material Angular. Por exemplo, precisamos importar "MatButtonModule" para usar botões, "MatCheckboxModule" para usar caixas de seleção, "MatFormFieldModule" para usar formulários, "MatInputModule" para usar entrada ... É realmente cansativo. Existe uma maneira de importar apenas uma ou duas vezes e então poderíamos começar a usar o Material Angular sem mais preocupações?
William Hou
1
IMPORTANTE: O pedido é importante!
Becario Senior
não funciona para mim, eu apenas usei este exemplo: material.angular.io/components/stepper/overview
tatsu 07/01
Isso funcionou para mim import { MatInputModule } from '@angular/material/input':
Jared Whipple
84

Solução 1 - importar MatInputModule

importar MatInputModuledentro do módulo ou sejaapp.module.ts

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

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

Solução 2 - Erros de ortografia

Certifique-se de adicionar matInpute faz distinção entre maiúsculas e minúsculas.

<input matInput type="text" />
WasiF
fonte
2
Ahh, isso estava me deixando louco. Razão um funcionou para mim. Eu sinto que isso deve ser especificado na documentação, mesmo que pareça óbvio agora.
Feign
Encontrei esse problema quando "matInput" estava ausente na instrução de entrada.
HadidAli
16

Citando a documentação oficial aqui :

Erro: mat-form-field deve conter um MatFormFieldControl

Este erro ocorre quando você não adicionou um controle de campo de formulário ao seu campo de formulário. Se seu campo de formulário contiver um elemento ou elemento nativo, verifique se você adicionou a diretiva matInput a ele e se importou MatInputModule. Outros componentes que podem atuar como um controle de campo de formulário incluem,, e qualquer controle de campo de formulário personalizado que você criou.

user158
fonte
13

Isso também pode acontecer se você tiver uma entrada adequada dentro de um campo de formulário mat , mas houver uma ngIf. Por exemplo:

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

No meu caso, mat-chip-listé suposto que "apareça" somente após os dados serem carregados. No entanto, a validação é realizada e mat-form-fieldatende às

O campo mat-form-field deve conter um MatFormFieldControl

Para corrigi-lo, o controle deve estar lá, então eu usei [hidden]:

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

Uma solução alternativa é proposta por Mosta: move * ngIf for mat-form-field:

<mat-form-field *ngIf="!_dataLoading">
    <mat-chip-list >
        <!-- other content here -->
    </mat-chip-list>
</mat-form-field>
Alexei
fonte
Acabei de ter um problema semelhante, consertei-o com algo semelhante ao que você está dizendo. Você tem o meu voto!
Alex
3
Graças, em vez de usar escondido você pode mover a condição ngIf em toda a tag mat-form-campo
Mosta
8
import {MatInputModule} from '@angular/material/input';



@NgModule({
    imports: [
        MatInputModule
    ],
    exports: [
        MatInputModule
    ]
})
Ib Abayomi Alli
fonte
3
Bem-vindo ao stackoverflow. Ao responder perguntas, inclua algumas explicações sobre o que o seu snippet de código faz e por que ele resolve a pergunta do OP. Para mais informações, verifique aqui Como responder
Djensen 15/01
5

Não tenho certeza se poderia ser tão simples, mas tive o mesmo problema, alterar "mat-input" para "matInput" no campo de entrada resolveu o problema. No seu caso, vejo "matinput" e está causando meu aplicativo com o mesmo erro.

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

insira a descrição da imagem aqui

"matInput"

insira a descrição da imagem aqui

ReturnTable
fonte
hmm não tenho certeza, você colou a saída gerada. No código real, ele já é matInput, se você ver "textbox-section". Não tenho problemas em fazê-lo funcionar apenas com o uso de material, é quando, ao tentar fazer meu próprio componente com projeção, ele para de funcionar. Meu plunker parece estar tendo problemas no caixa eletrônico, espero que ele se conserte durante o dia.
Viktor Eriksson
Oh, entendo, meu mal. Este foi um tiro no escuro de qualquer maneira. Vou seguir para ver se alguém pode realmente apresentar o ângulo de inclinação correto, estou curioso sobre esse problema.
ReturnTable
2
Foi o que aconteceu comigo, eu ter esquecido de mudança mdInputpara matInput.
Ebraheem Alrabee '
2
Angular 5: o atributo da tag <input> deve estar em matInputvez de mat-input.
Stavm
5

Se alguém ficou com esse erro depois de tentar aninhar um <mat-checkbox>, fique de bom humor! Não funciona dentro de uma <mat-form-field>tag.

Mina
fonte
5

se alguém estiver tentando aninhar um <mat-radio-group>dentro de um <mat-form-field> como abaixo, você receberá este erro

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

remova as <mat-form-field>tags principais

Steve Sonius
fonte
Eu estava tendo esse problema e tinha um trecho de marcação com esse tipo de coisa. A remoção do mat-form-fieldproblema fez com que eu desaparecesse.
Andrew Gray
Existe uma razão que <mat-form-field>não suporte o grupo de rádio dentro dele? Eu também estava tendo esse problema e não pensei em remover as tags de campo do formulário, porque parecia não ser a coisa certa a fazer, já que muitos exemplos de materiais de formulário da interface do usuário usam <mat-form-field>. Eu tenho todos os vários módulos de entrada de material para formulários, selecione listas suspensas e grupos de rádio definidos em meu app.module.ts como muitas das outras referências de respostas.
Alex
Não consigo acreditar .... Tento de tudo e nada para trabalhar .... e depois de alguns dias de dor encontrei essa solução tão simples ... obrigado, companheiro
Arter
3

Também tive esse problema e tenho um <mat-select>elemento no meu modelo, quando importo o MatSelectModule para o Módulo, ele funciona, não produz ciência, mas ainda espero que possa ajudá-lo.

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
fonte
Funciona como sem importar o módulo, o controle mat-form-field não entende o que é um mat-select. Quando é importado, ele pode corrigir todas as informações e, portanto, pode analisar o modelo sem erros adicionais.
Peters
2

Infelizmente, não posso apenas comentar algumas respostas já boas, pois ainda não tenho os pontos SO, no entanto, existem três módulos principais que você precisará verificar para importar para o módulo pai do componente, além do que você precisa importar diretamente para o seu componente. Eu queria compartilhá-los brevemente e destacar o que eles fazem.

  1. MatInputModule
  2. MatFormFieldModule
  3. ReactiveFormsModule

Os dois primeiros são para material angular. Muitas pessoas novas no Material Angular encontrarão instintivamente um desses e não perceberão que a construção de um formulário exige ambos.

Então, qual é a diferença entre eles?

MatFormFieldModule abrange todos os diferentes tipos de campos de formulário que o Material Angular tem disponível. Este é mais um módulo de alto nível para campos de formulário em geral, enquanto o MatInputModule é especificamente para tipos de campos de 'entrada', ao contrário de caixas de seleção, botões de opção etc.

O terceiro item da lista acima é o Módulo de formas reativas da Angular. O Módulo de formulários reativos é responsável por uma tonelada de amor angular oculto. Se você vai trabalhar com o Angular, eu recomendo que você gaste algum tempo lendo o Angular Docs. Eles têm todas as suas respostas. A criação de aplicativos raramente NÃO envolve formulários e, na maioria das vezes, seu aplicativo envolve formulários reativos. Por esse motivo, leia estas duas páginas.

Documentos angulares: formulários reativos

Documentos angulares: módulo de formulários reativos

O primeiro documento 'Formas reativas' será sua arma mais poderosa quando você começar, e o segundo documento será sua arma mais poderosa quando você acessar aplicativos mais avançados de Formas reativas angulares.

Lembre-se, eles precisam ser importados diretamente para o módulo do seu componente, não para o componente em que você os está usando. Se bem me lembro, no Angular 2, importamos todo o conjunto de módulos de material angular no módulo principal do aplicativo e depois importamos o que precisávamos diretamente em cada um de nossos componentes. O método atual é IMO muito mais eficiente, porque garantimos a importação de todo o conjunto de módulos de material angular, se usarmos apenas alguns deles.

Espero que isso forneça um pouco mais de insight sobre a construção de formulários com o material angular.

outro codificador
fonte
2

Se todas as respostas principais de estrutura / configuração de código acima não resolverem o seu problema, aqui está mais uma coisa para verificar: verifique se você não invalidou de alguma forma sua <input>tag.

Por exemplo, recebi a mesma mat-form-field must contain a MatFormFieldControlmensagem de erro após colocar acidentalmente um requiredatributo após uma barra de fechamento automático /, o que invalidou efetivamente o meu <input/>. Em outras palavras, eu fiz isso (veja o final dos atributos da tag de entrada):

errado :

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

direito :

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

Se você cometer esse erro ou algo mais para invalidar o seu <input>, poderá receber o mat-form-field must contain a MatFormFieldControlerro. Enfim, isso é apenas mais uma coisa a ser procurada durante a depuração.

cjn
fonte
2

O mesmo erro pode ocorrer se você tiver um slide de tapete dentro de um tapete de campo como o único elemento no meu caso

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

Isso pode acontecer se você tiver vários atributos na <mat-form-field> solução Simples: mover o slide para a raiz

Kisinga
fonte
1
Isso salvou minha vida. Obrigado.
Paulo Pedroso
1

Você pode tentar seguir este guia e implementar / fornecer seu próprio MatFormFieldControl

rivanov
fonte
1

Eu removi acidentalmente o matInput diretiva do campo de entrada que causou o mesmo erro.

por exemplo.

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

código fixo

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

MatRadioModule não funcionará dentro do MatFormField. Os documentos dizem

Este erro ocorre quando você não adicionou um controle de campo de formulário ao seu campo de formulário. Se seu campo de formulário contiver um elemento ou elemento nativo, verifique se você adicionou a diretiva matInput a ele e se importou MatInputModule. Outros componentes que podem atuar como um controle de campo de formulário incluem <mat-select>, <mat-chip-list> e quaisquer controles de campo de formulário personalizados criados por você.

intotecho
fonte
1

No meu caso, um dos meus parênteses de fechamento para "onChanges ()" estava ausente no elemento de entrada e, portanto, o elemento de entrada aparentemente não estava sendo renderizado:

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

Uma solução parcial é agrupar o campo do formulário do material em um componente personalizado e implementar a ControlValueAccessorinterface nele. Além da projeção de conteúdo, o efeito é praticamente o mesmo.

Veja o exemplo completo no Stackblitz.

Eu usei FormControl( formas reativas ) dentro, CustomInputComponentmas FormGroupou FormArraydeveria funcionar também se você precisar de um elemento de formulário mais complexo.

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

Você perdeu a matInput diretiva na sua tag de entrada.

Isaac Pitwa
fonte
1

Você precisa importar o MatInputModule para o arquivo app.module.ts

import {MatInputModule} de '@ 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
fonte
1

Você pode definir a aparência = "preencher" dentro da sua tag mat-form-field, funciona para mim

<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
fonte
Isso corrigiu meu problema. Você pode explicar o que appearence = "fill"está fazendo aqui
IamGrooot
1

Angular 9+ ... Material 9+

Notei que 3 erros podem dar origem ao mesmo erro:

  1. Verifique se você importou MatFormFieldModule e MatInputModule no app.module ou no module.ts em que seus componentes estão sendo importados (no caso de módulos aninhados)
  2. Quando você quebra botões ou caixas de seleção de material no campo de formulário mat. Consulte a lista de componentes de material que podem ser agrupados com campo de formulário de esteira
  3. Quando você falha ao incluir matInput em sua tag. ou seja, <input matInput type = "number" step = "0.01" formControlName = "price" />
7guyo
fonte
0

No meu caso, mudei isso:

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

para isso:

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

Adicionar a diretiva matInput à tag de entrada foi o que corrigiu esse erro para mim.

Gilmourguru
fonte
0

Você pode ter perdido a importação do MatInputModule

Pranith Baggan
fonte
0

Nota Algum tempo ocorre um erro, quando usamos a tag "mat-form-field" ao redor do botão enviar, como:

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

Portanto, por favor, não use essa tag no botão enviar

M Abdullah
fonte
0

use provedores no arquivo component.ts

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

A nova importação atualizada do Módulo MatInput é:

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

Conforme API de materiais angulares

SaiSurya
fonte
-1

Eu tive o mesmo problema

questão é simples

somente você deve importar dois módulos para o seu projeto

MatFormFieldModule MatInputModule

Fatih Çakıroğlu
fonte
-1

Eu estava recebendo o mesmo problema devido ao elemento comentado da seguinte forma.

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

campo de formulário deve ter elemento! (por exemplo, a entrada, área de texto, seleção, etc.)

U_R_Naveen UR_Naveen
fonte