Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
897 views
in Technique[技术] by (71.8m points)

angular - Custom Controls with Reactive Forms

I am using Angular 7, Angular Material controls with Reactive Forms.

I created custom text (matInput type="text"), number (matInput type="number"), select (matSelect) controls with Angular Material with mat-form-field

Here is the stackblitz for my example.

I am trying to attach the custom form controls to reactive form and trying to fire any validations on the form group automatically.

I am using ControlValueAccessor to achieve this, however my Select is not being identified as form control and no value is being recorded in the form control on the form.

Any help in this regard is highly appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

UPDATE Jenson-button-event find a better option, see the SO answer

Looking into your code, I see that you use Angular Material to create your custom FormControl. Well, The problem when use Angular material is how make that the "errors" appears.

When we use <mat-error> the error appears if the control is invalid. Take account that is invalid our custom form conrol, NOT the input-material. How avoid this inconvenience?

The solution is using a CustomFieldErrorMatcher. if we can create a CustomFiledErrorMatcher that take account the errors of our customFormControl, we can do some like

class CustomFieldErrorMatcher implements ErrorStateMatcher {
  constructor(private customControl: FormControl) { }
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return control.dirty && this.customControl.invalid;
  }
}

Well, it's only in ngAfterView write some like

  ngAfterViewInit(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      setTimeout(() => {
        this.control = ngControl.control as FormControl;
      })
    }
  }

Has a function

errorMatcher() {
    return new CustomFieldErrorMatcher(this.control)
  }

And create our custom-formControl.html like

<mat-form-field>
    <mat-select [ngModel]="value" (ngModelChange)="value=$event;onChange($event)" 
          [placeholder]="placeholder" [disabled]="disabled"
          [errorStateMatcher]="errorMatcher()">
        <mat-option *ngFor="let option of optionList" [value]="option.value">
            {{ option.label }}
        </mat-option>
    </mat-select>
  <mat-error *ngIf="control?.hasError('required')">Required</mat-error>
  <mat-error *ngIf="control?.hasError('error')">{{control?.errors.error}}</mat-error>
</mat-form-field>

You can see in the stackblitz two forms, one that use a customFormControl, and another one in clasic mode


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...