We are trying to build our own form-field-Components at our Company. We are trying to wrap material design\'s Components like this:
field:
i was getting the same issue due to commented element as follows.
<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>
form field should have element! (e.g. the input, textarea, select, etc.)
Quoting from the official documentation here:
Error: mat-form-field must contain a MatFormFieldControl
This error occurs when you have not added a form field control to your form field. If your form field contains a native or element, make sure you've added the matInput directive to it and have imported MatInputModule. Other components that can act as a form field control include , , and any custom form field controls you've created.
The same error can occur if you have a mat slide within a mat from field as the only element in my case I had
<mat-form-field>
<mat-slide-toggle [(ngModel)]="myvar">
Some Text
</mat-slide-toggle>
</mat-form-field>
This might happen if you had several attributes within the <mat-form-field>
Simple solution was to move the slide toggle to the root
if anyone is trying to nest a <mat-radio-group>
inside a <mat-form-field>
like below, you will get this 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>
remove the parent <mat-form-field>
tags
Note Some time Error occurs, when we use "mat-form-field" tag around submit button like:
<mat-form-field class="example-full-width">
<button mat-raised-button type="submit" color="primary"> Login</button>
</mat-form-field>
So kindly don't use this tag around submit button
A partial solution is to wrap the material form field in a custom component and implement the ControlValueAccessor
interface on it. Besides content projection the effect is pretty much the same.
See full example on Stackblitz.
I used FormControl
(reactive forms) inside CustomInputComponent
but FormGroup
or FormArray
should work too if you need a more complex form element.
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>