3
votes

I'd like to implement an Angular Material custom form field following this guide: https://material.angular.io/guide/creating-a-custom-form-field-control

But I keep having this error: ERROR Error: mat-form-field must contain a MatFormFieldControl.

According to the documentation:

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.

But adding a matInput directive to the tags does not change anything. It's like it's blind because the tags are embedded in this new component <example-tel-input>

The mat-form-field:

<mat-form-field>
  <example-tel-input placeholder="Phone number" required></example-tel-input>
  <mat-icon matSuffix>phone</mat-icon>
  <mat-hint>Include area code</mat-hint>
</mat-form-field>

The component with the inputs:

<div [formGroup]="parts" class="example-tel-input-container">
  <input class="example-tel-input-element" formControlName="area" size="3" aria-label="Area code" (input)="_handleInput()">
  <span class="example-tel-input-spacer">&ndash;</span>
  <input class="example-tel-input-element" formControlName="exchange" size="3" aria-label="Exchange code" (input)="_handleInput()">
  <span class="example-tel-input-spacer">&ndash;</span>
  <input class="example-tel-input-element" formControlName="subscriber" size="4" aria-label="Subscriber number" (input)="_handleInput()">
</div>

Stackblitz: https://stackblitz.com/edit/angular-9fyeha

What am I missing?

2

2 Answers

1
votes

The documentation didn't mention the fact that you should import material classes from the same entry points, either

main entry point:

app.module.ts

import {
  MatIconModule,
  MatFormFieldModule, // it's redundant here since MatInputModule already exports it
  MatInputModule,
  MatSelectModule
} from "@angular/material";

example-tel-input-example.component.ts

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

or

secondary entry points:

app.module.ts

import { MatSelectModule } from "@angular/material/select";
import { MatIconModule } from "@angular/material/icon";
import { MatInputModule } from "@angular/material/input";

example-tel-input-example.component.ts

import { MatFormFieldControl } from '@angular/material/form-field';

Forked Stackblitz

Why is it so important?

Because in order to get nested form control Angular material uses @ContentChild(MatFormFieldControl) decorator and MatFormFieldControl class should come from the same package otherwise instanceof will return false

-1
votes

I added hidden input in your form-field-custom-control-example.component and it worked.

<mat-form-field>
  <input matInput style="display:none">
  <example-tel-input placeholder="Phone number" required></example-tel-input>
  <mat-icon matSuffix>phone</mat-icon>
  <mat-hint>Include area code</mat-hint>
</mat-form-field>