Ошибка "mat-form-field must contain a MatFormFieldControl" в Angular Material
Причина ошибки
Ошибка возникает, потому что Angular Material ожидает, что внутри <mat-form-field> будет находиться специализированный контрол, реализующий интерфейс MatFormFieldControl. Обычный HTML-элемент <input type="text"> не является таким контролом. Для работы с текстовыми полями в Angular Material используется директива matInput, которая подключается через модуль MatInputModule.
Решение
Вам нужно:
- Импортировать
MatInputModuleв ваш модуль - Добавить директиву
matInputк элементу<input> - Убрать лишний тег
<label>(или использоватьmat-label)
Шаг 1: Импорт модулей
В app.module.ts импортируйте оба модуля:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
MatFormFieldModule,
MatInputModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Шаг 2: Исправьте шаблон
В app.component.html используйте правильную структуру:
<mat-form-field appearance="outline">
<mat-label>Имя пользователя</mat-label>
<input matInput type="text" placeholder="Введите имя">
</mat-form-field>
Ключевые моменты:
- matInput — директива, которая связывает элемент input с mat-form-field
- mat-label — правильный способ задания подписи (вместо обычного <label>)
- appearance — необязательный атрибут для стилизации (fill, outline, legacy)
- Обязательно импортируйте
BrowserAnimationsModuleдля анимаций Material
Шаг 3: Проверка импортов
Если ошибка остаётся, проверьте:
- Установлены ли пакеты:
npm install @angular/material @angular/cdk @angular/animations - Добавлен ли стиль темы Material в
angular.jsonилиstyles.scss:@import '@angular/material/prebuilt-themes/indigo-pink.css'; - Не забыли ли вы
MatInputModule— это самая частая причина ошибки
Полный рабочий пример
Вот минимальный рабочий компонент:
// app.component.ts
import { Component } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
template: `
<mat-form-field>
<mat-label>Email</mat-label>
<input matInput [formControl]="emailControl" placeholder="example@mail.com">
<mat-error *ngIf="emailControl.invalid">Введите корректный email</mat-error>
</mat-form-field>
`
})
export class AppComponent {
emailControl = new FormControl('', [Validators.email, Validators.required]);
}
Не забудьте также импортировать ReactiveFormsModule в модуль, если используете formControl.
Альтернативный подход: использование matNativeControl
Если вы не хотите импортировать MatInputModule, можно использовать нативную директиву matNativeControl, которая доступна в том же модуле MatFormFieldModule. Однако это менее гибкий вариант.
<mat-form-field>
<mat-label>Имя</mat-label>
<input matNativeControl type="text">
</mat-form-field>
Недостатки:
- Не поддерживает кастомные контролы (календари, селекты)
- Ограниченная стилизация
- Нет интеграции с реактивными формами (
formControl) без дополнительных настроек
Диагностика проблемы
Если оба решения не работают, проверьте:
- Версию Angular Material — для Angular 15+ используйте
@angular/material@15 - Наличие
<router-outlet>или других структур, которые могут "разрывать" DOM — mat-form-field должен быть прямым родителем контрола - Консоль браузера на наличие других ошибок, которые могут блокировать загрузку модулей
Рекомендую всегда использовать matInput — это стандартный и самый поддерживаемый способ.