如何根据之前的字段输入更改验证 angular

How can I change the validations based on previous field input angular

我在 angular 中有两个反应形式的字段。我需要验证第二个字段并根据选择的第一个字段选项显示错误消息。

字段一:

<label>ID proof </b><span class="asterisk">*</span></label>
   <mat-form-field appearance="outline">
     <mat-select name="idproofs" placeholder="IDProof name" required formControlName="idProof" class="form-control">
     <mat-option *ngFor="let idproof of idproofs" [value]="idproof.value">
        {{idproof.viewValue}}
     </mat-option>
     </mat-select>
  </mat-form-field>

字段二:

<label>ID proof number </b><span class="asterisk">*</span></label>
    <mat-form-field appearance="outline">
       <input matInput placeholder="ID Proof Number" required formControlName="idFroofNumber" class="form-control">
    <mat-error *ngIf="PGroup.controls['idProofNumber'].hasError('required')">
       ID proof number is required!
    </mat-error>
   </mat-form-field>

Example 在第一个字段中如果我选择选项 Adhaar number 那么在第二个字段中验证必须是只有 12 位字符的数字最大长度。

如果我选择 PAN 编号,那么只有验证将是最大长度为 10 个字符的字母数字。因此,如果我也可以提供错误消息验证。我怎样才能做到这一点

编辑 添加了 ts formcontrol

this.PGroup = this._formBuilder.group({
      idProof: ['', Validators.required],
      idProofNumber: ['', [Validators.required,Validators.pattern(/^[\w\s]+$/)]]
});

你能提供你的ts代码吗?我看到您将 ngModel 与 formControlName 结合使用,我认为它是反应式方法与模板驱动方法的结合。 无论如何,这是我的建议。 以这种方式使用反应式方法,(仅建议,您可以根据自己的喜好了解并实施)

// attr declarations
fieldOne = new FormControl('',[]); // initial value and validators inside array
fieldTwo = new FormControl('', []); // initialValue and validators

// ngOnInit
fieldOne.valueChanges.
.pipe(
debounceTime(100),   // dalay after every change to update your validations
distinctUntilChanged(), // only update validators when value change
tap(value => {

// depend on your options you can use switch here
   if(value === 'Adhaar number'){
    this.fieldTwo.setValidators([Validators.required,Validators.maxLength(12)]);
    this.fieldTwo.updateValueAndValidity();
  } else 
 if(value === 'PAN number'){
    this.fieldTwo.setValidators([Validators.required,Validators.maxLength(10)]);
    this.fieldTwo.updateValueAndValidity();
  } else {
this.fieldTwo.setValidators([Validators.required]);
    this.fieldTwo.updateValueAndValidity();
}
})

)
.subscribe()

根据您可能的错误更新您的html。

您也可以使用带有两个字段的 formGroup 而不是单独的 formControl,并且只需将订阅从 this.fieldOne.valueChanges 更改为 this.form.get('fieldOne').valueChanges


请记住取消订阅此订阅。我建议 https://www.npmjs.com/package/@ngneat/until-destroy

我想你可以这样做,

假设您有一个名为 AppComponent 的组件,

import { Component } from '@angular/core';
import { 
  FormBuilder,
  FormGroup,
  FormControl, 
  ValidationErrors, 
  AbstractControl, 
  ValidatorFn 
} from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
    title = 'Whosebug-examples';
    panelOpenState = false;
    idproofOptions: string[] = ['Aadhar','PAN'];
    idproofsForm: FormGroup;

    get idproofsFormControl(): FormControl {
      // debugger
      return this.idproofsForm.controls['idproofs'] as FormControl;
    }

    get idproofsInputFormControl(): FormControl {
      // debugger
      return this.idproofsForm.controls['idproofsInput'] as FormControl;
    }

    idproofInputAadharValidation(): ValidatorFn {
      return (control: AbstractControl): ValidationErrors | null => {
        // debugger
        const pattern = new RegExp("^[0-9]{10}$");
        if (pattern.test(control.value)) {
          return null;
        } else {
          return {
            aadharError: 'Aadhar number is not correct'
          };
        }
      };
    }

    idproofInputPANValidation(): ValidatorFn {
      return (control: AbstractControl): ValidationErrors | null => {
        // debugger
        const pattern = new RegExp("^[a-zA-Z0-9]+$");
        if (pattern.test(control.value)) {
          return null;
        } else {
          return {
            panError: 'PAN number is not correct'
          };
        }
      };
    }

    constructor(
      private fb: FormBuilder
    ) { 
      this.idproofsForm = new FormGroup(
        {
          idproofs: new FormControl(''),
          idproofsInput: new FormControl('')
        }
      );
    }

    ngOnInit() {
      this.idproofsForm.valueChanges.subscribe(
        field => {
          // debugger
          console.log(this.idproofsForm.controls['idproofsInput']);
          if (field['idproofs'] && field['idproofs'] === 'PAN') {
            this.idproofsInputFormControl.clearValidators();
            this.idproofsInputFormControl.setValidators(this.idproofInputPANValidation());
          } else if (field['idproofs'] && field['idproofs'] === 'Aadhar') {
            this.idproofsInputFormControl.clearValidators();
            this.idproofsInputFormControl.setValidators(this.idproofInputAadharValidation());
          }
          // debugger
        }
      );
    }

}

您的 HTML 可以看起来像这样,

<label>ID proof<span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
  <mat-select [formControl]="idproofsFormControl" name="idproofs" placeholder="IDProof name" required class="form-control">
    <mat-option  *ngFor="let idproof of idproofOptions" [value]="idproof">
      {{idproof}}
    </mat-option> 
  </mat-select>
</mat-form-field>
<br/>
<!-- {{idproofsInputFormControl|json}} -->
<label>ID proof number<span class="asterisk">*</span></label>
<mat-form-field appearance="outline">
  <input matInput placeholder="ID Proof Number" required [formControl]="idproofsInputFormControl" class="form-control">
  <mat-error *ngIf="idproofsInputFormControl.errors">
      {{idproofsInputFormControl.errors['aadharError']}}
  </mat-error>
</mat-form-field>

看下面截图中的错误

注意:我的建议是您不要使用 ngModel,反应式方法要好得多,您可能需要稍微更改此代码以满足您的要求,但我相信它应该会有帮助