Introdução: por que seu formulário Angular está gritando com um erro?
\nVocê já se deparou com a seguinte situação: está escrevendo um formulário bonito no Angular Material, tudo parece perfeito, mas o console do navegador de repente exibe a mensagem:
\nmat-form-field must contain a MatFormFieldControl\nOu, se você estiver usando o modo estrito do TypeScript, pode aparecer algo como:
\nError: mat-form-field must contain a MatFormFieldControl. Did you forget to add a directive that implements MatFormFieldControl?\nEste é um dos erros mais populares no Stack Overflow (milhares de visualizações!), e hoje vamos analisá-lo de ponta a ponta. Você aprenderá não apenas como corrigir esse problema, mas também por que ele ocorre. E o principal: aprenderá a criar seus próprios controles para o Angular Material, se o padrão MatInput não atender às suas necessidades.
Vamos lá! 🚀
\n\nO que é MatFormFieldControl e para que serve?
\nAntes de tratar o erro, vamos entender a anatomia do Angular Material. mat-form-field é um contêiner que adiciona a estilização do Material Design (rótulo, sublinhado, dicas, erros). Mas por si só ele não exibe nada. Ele precisa de um "filho" — uma diretiva ou componente que implemente a interface MatFormFieldControl.
Essa interface (ou classe abstrata) descreve como o controle interage com o formulário: como obter o valor, como exibir o erro, como lidar com o foco. A implementação padrão é o MatInput. Se você escrever:
<mat-form-field>\n <input matInput placeholder="Nome">\n</mat-form-field>\n— a diretiva matInput implementa automaticamente o MatFormFieldControl.
O erro ocorre quando o Angular não encontra nenhum elemento filho com essa implementação. Por exemplo:
\n<mat-form-field>\n <input placeholder="Nome"> <!-- Sem matInput! -->\n</mat-form-field>\nOu quando você tenta usar um componente personalizado que não implementou a interface.
\n\nCausas típicas do erro (e como corrigi-las)
\n\n1. Esqueceu de adicionar a diretiva matInput
\nA causa mais simples. Você simplesmente não colocou matInput no elemento <input>.
Incorreto:
\n<mat-form-field>\n <input placeholder="Email">\n</mat-form-field>\nCorreto:
\n<mat-form-field>\n <input matInput placeholder="Email">\n</mat-form-field>\nVerifique também se você importou o MatInputModule no seu módulo:
import { MatInputModule } from '@angular/material/input';\n\n@NgModule({\n imports: [MatInputModule]\n})\nexport class AppModule { }\n\n2. Usando o elemento HTML errado
\nO MatInput funciona apenas com <input> e <textarea>. Se você tentar envolver um <div> comum ou <select> (sem mat-select) em um mat-form-field, receberá o erro.
Incorreto:
\n<mat-form-field>\n <div>Algum conteúdo</div>\n</mat-form-field>\nCorreto: use os componentes Material apropriados:
\n<mat-form-field>\n <mat-select placeholder="Cidade">\n <mat-option value="1">São Paulo</mat-option>\n </mat-select>\n</mat-form-field>\nPara mat-select, é necessário importar o MatSelectModule.
3. Componente personalizado não implementa MatFormFieldControl
\nEste é um caso mais complexo. Suponha que você criou seu próprio componente para entrada de data ou classificação. O Angular Material não sabe sobre ele. É necessário "ensiná-lo" explicitamente.
\n