title: Angular: mat-form-field must contain a MatFormFieldControl
body: <p>I am trying to add a form field with custom telephone number input control. I used the example of the phone from <a href="https://material.angular.io/components/form-field/examples" rel="noreferrer">https://material.angular.io/components/form-field/examples</a>.</p>
  <p>Here is the code:</p>
  <pre class="lang-html prettyprint-override"><code>&lt;mat-form-field&gt;
    &lt;example-tel-input placeholder=&quot;Phone number&quot; required&gt;&lt;/example-tel-input&gt;
    &lt;mat-icon matSuffix&gt;phone&lt;/mat-icon&gt;
    &lt;mat-hint&gt;Include area code&lt;/mat-hint&gt;
  &lt;/mat-form-field&gt;
  </code></pre>
  <pre><code>import {FocusMonitor} from '@angular/cdk/a11y';
  import {coerceBooleanProperty} from '@angular/cdk/coercion';
  import {Component, ElementRef, Input, OnDestroy} from '@angular/core';
  import {FormBuilder, FormGroup} from '@angular/forms';
  import {MatFormFieldControl} from '@angular/material';
  import {Subject} from 'rxjs';
  
  /** @title Form field with custom telephone number input control. */
  @Component({
    selector: 'form-field-custom-control-example',
    templateUrl: 'form-field-custom-control-example.html',
    styleUrls: ['form-field-custom-control-example.css'],
  })
  export class FormFieldCustomControlExample {}
  
  /** Data structure for holding telephone number. */
  export class MyTel {
    constructor(public area: string, public exchange: string, public subscriber: string) {}
  }
  
  /** Custom `MatFormFieldControl` for telephone number input. */
  @Component({
    selector: 'example-tel-input',
    templateUrl: 'example-tel-input-example.html',
    styleUrls: ['example-tel-input-example.css'],
    providers: [{provide: MatFormFieldControl, useExisting: MyTelInput}],
    host: {
      '[class.example-floating]': 'shouldLabelFloat',
      '[id]': 'id',
      '[attr.aria-describedby]': 'describedBy',
    }
  })
  export class MyTelInput implements MatFormFieldControl&lt;MyTel&gt;, OnDestroy {
    static nextId = 0;
  
    parts: FormGroup;
    stateChanges = new Subject&lt;void&gt;();
    focused = false;
    ngControl = null;
    errorState = false;
    controlType = 'example-tel-input';
    id = `example-tel-input-${MyTelInput.nextId++}`;
    describedBy = '';
  
    get empty() {
      const {value: {area, exchange, subscriber}} = this.parts;
  
      return !area &amp;&amp; !exchange &amp;&amp; !subscriber;
    }
  
    get shouldLabelFloat() { return this.focused || !this.empty; }
  
    @Input()
    get placeholder(): string { return this._placeholder; }
    set placeholder(value: string) {
      this._placeholder = value;
      this.stateChanges.next();
    }
    private _placeholder: string;
  
    @Input()
    get required(): boolean { return this._required; }
    set required(value: boolean) {
      this._required = coerceBooleanProperty(value);
      this.stateChanges.next();
    }
    private _required = false;
  
    @Input()
    get disabled(): boolean { return this._disabled; }
    set disabled(value: boolean) {
      this._disabled = coerceBooleanProperty(value);
      this.stateChanges.next();
    }
    private _disabled = false;
  
    @Input()
    get value(): MyTel | null {
      const {value: {area, exchange, subscriber}} = this.parts;
      if (area.length === 3 &amp;&amp; exchange.length === 3 &amp;&amp; subscriber.length === 4) {
        return new MyTel(area, exchange, subscriber);
      }
      return null;
    }
    set value(tel: MyTel | null) {
      const {area, exchange, subscriber} = tel || new MyTel('', '', '');
      this.parts.setValue({area, exchange, subscriber});
      this.stateChanges.next();
    }
  
    constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef&lt;HTMLElement&gt;) {
      this.parts = fb.group({
        area: '',
        exchange: '',
        subscriber: '',
      });
  
      fm.monitor(elRef, true).subscribe(origin =&gt; {
        this.focused = !!origin;
        this.stateChanges.next();
      });
    }
  
    ngOnDestroy() {
      this.stateChanges.complete();
      this.fm.stopMonitoring(this.elRef);
    }
  
    setDescribedByIds(ids: string[]) {
      this.describedBy = ids.join(' ');
    }
  
    onContainerClick(event: MouseEvent) {
      if ((event.target as Element).tagName.toLowerCase() != 'input') {
        this.elRef.nativeElement.querySelector('input')!.focus();
      }
    }
  
  
    }
  </code></pre>
  <p>example-tel-input-example.html</p>
  <pre><code>  &lt;div [formGroup]=&quot;parts&quot; class=&quot;example-tel-input-container&quot;&gt;
        &lt;input class=&quot;example-tel-input-element&quot; formControlName=&quot;area&quot; size=&quot;3&quot;&gt;
        &lt;span class=&quot;example-tel-input-spacer&quot;&gt;&amp;ndash;&lt;/span&gt;
        &lt;input class=&quot;example-tel-input-element&quot; formControlName=&quot;exchange&quot; size=&quot;3&quot;&gt;
        &lt;span class=&quot;example-tel-input-spacer&quot;&gt;&amp;ndash;&lt;/span&gt;
        &lt;input class=&quot;example-tel-input-element&quot; formControlName=&quot;subscriber&quot; size=&quot;4&quot;&gt;
      &lt;/div&gt;
  </code></pre>
  <p>But I get the following error:</p>
  <blockquote>
  <p>ERROR Error: mat-form-field must contain a MatFormFieldControl.</p>
  </blockquote>