首页 > 解决方案 > 使用 Angular 6 中的自定义表单控件进行自定义验证

问题描述

我创建了 app-input 组件来显示输入文本框。

我无法应用自定义表单验证。

你有什么主意吗?

标签: angularangular6

解决方案


由于没有在说明中给出示例,因此假设您必须发布一个表格来捕获虚构的帐户。AccountService 正在向 API 发送 HTTP。

我的自定义验证器名称是 accountIdValidator,它希望帐户 ID 以 123 开头。

参考下面的代码

In Componenet TS
--------------------
import { Component, OnInit, Input } from '@angular/core';
import { FormGroup, AbstractControl, FormBuilder, Validators, NgForm } from '@angular/forms';
import { Router } from '@angular/router';

@Component({
  selector: 'app-survey-child',
  templateUrl: './survey-child.component.html',
  styleUrls: ['./survey-child.component.css']
})
export class SurveyChildComponent implements OnInit {
  @Input() surveyChildValue: string;
  public testValue: string;
  
  dealForm: FormGroup;
  dealName: AbstractControl;
  accountShortName = '';
  accountId = '';
  dealId = 0;
  isLoadingResults = false;

  matcher = new MyErrorStateMatcher();

  constructor(private router: Router, private api: AccountService, private formBuilder: FormBuilder) { }


  ngOnInit() {
    this.dealForm = this.formBuilder.group({
      'accountName': [null, Validators.required],
      'accountShortName': [null, null],
      'accountId': ['', Validators.compose([Validators.required, accountIdValidator])]
    });
    console.log('initialize account add');
    this.dealName = this.dealForm.controls['dealName'];

    this.dealName.valueChanges.subscribe((value: string) => {
      console.log('deal name changed to:', value);
    });

    this.dealForm.valueChanges.subscribe((form: any) => {
      console.log('form changed to:', form);
    });
  }



  onFormSubmit(form: NgForm) {
    this.isLoadingResults = true;
    this.api.addAccount(form)
      .subscribe((res: { [x: string]: any; }) => {
        const response = res;
        this.isLoadingResults = false;
        //  this.router.navigate(['/account-details', id]);
        console.log('Account added succesfully: ' + response);
      }, (err) => {
        console.log('Error: Account Add :  ' + err);
        this.isLoadingResults = false;
      });
  }


}

//Custom Validations
function accountIdValidator(control: FormControl): { [s: string]: boolean } {
  if (!control.value.match(/^123/)) {
    //should start with 123
    return { invalidAccountId: true };
  }
}


/** Error when invalid control is dirty, touched, or submitted. */
export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const isSubmitted = form && form.submitted;
    return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
  }
}
}
<div class="example-container mat-elevation-z8">
  <!--<div class="button-row">
    <a mat-flat-button color="primary" [routerLink]="['/accounts']"><mat-icon>list</mat-icon></a>
  </div>-->
  <mat-card class="example-card">
    <form [formGroup]="dealForm" (ngSubmit)="onFormSubmit(dealForm.value)">
      <mat-form-field class="example-full-width">
        <input matInput placeholder="Deal Name" formControlName="dealName" [errorStateMatcher]="matcher" id="dealNameInput">
        <mat-error>
          <span *ngIf="!dealForm.get('dealName').valid && dealForm.get('dealName').touched">Please enter valid Deal Name</span>
        </mat-error>
      </mat-form-field>
      <mat-form-field class="example-full-width">
        <input matInput placeholder="Account Name" formControlName="accountShortName" [errorStateMatcher]="matcher">
      </mat-form-field>
      <mat-form-field class="example-full-width">
        <input matInput placeholder="Account Id" formControlName="accountId" [errorStateMatcher]="matcher">
      </mat-form-field>

      <div class="button-row">
        <button type="submit" [disabled]="!dealForm.valid" mat-flat-button color="primary"><mat-icon>Save</mat-icon></button>
      </div>
    </form>
  </mat-card>
</div>


推荐阅读