Phone number <" /> Phone number <" /> Phone number <"/>

Custom control used with Validators.required in a reactive form control does not display the indicator

28 Views Asked by At

Let's say we have 2 inputs: MatInput control and custom input control.

<div [formGroup]="form">
  <mat-form-field>
    <mat-label>Phone number</mat-label>
    <example-tel-input formControlName="tel"></example-tel-input>
    <mat-icon matSuffix>phone</mat-icon>
    <mat-hint>Include area code</mat-hint>
  </mat-form-field>
  <mat-form-field>
    <mat-label>Mobile number</mat-label>
    <input type="text" matInput formControlName="mobile" />
  </mat-form-field>
</div>

If we imperatively require these two components:

  form: FormGroup = new FormGroup({
    tel: new FormControl(null, [Validators.required]),
    mobile: new FormControl(null, [Validators.required]),
  });

mobile displays an indicator (*) and the tel does not. In the docs it says that:

Notice that the required attribute is still present in the template. Although it's not necessary for validation, it should be retained for accessibility purposes.

Meaning that for a custom component I need to include required in the HTML template.

<example-tel-input formControlName="tel" required></example-tel-input>

I wonder why this is the case.

  1. This is duplicate code.
  2. How can MatInput access the validator required in the parent class and custom control can not?

Here is the Stackblitz.

1

There are 1 best solutions below

0
VPNer On

After some help and investigation into with MatInput, someone upon suggestion I was able to access the validator via ngControl. In the custom component class constructor there was already: @Optional() @Self() public ngControl: NgControl Then there needs to be no default _required value (undefined): private _required: boolean | undefined;

@Input()
  get required(): boolean {
    return (
      this._required ??
      this.ngControl?.control?.hasValidator(Validators.required) ??
      false
    );
  }