如何有条件地验证反应式表单中的输入字段?

How do I conditionally validate input fields in my reactive form?

我有一个表格,用户可以在其中注册自己或访客。如果用户自己注册,我不需要验证来宾信息输入字段,如果用户正在注册来宾,我确实需要这样做。这是link到stackblitz.

这是我的反应式表单的简化示例,其中包含验证但无法正常工作:

export class AppComponent {
  name = 'Angular ' + VERSION.major;

  guestInfoValidators = [];

  profileForm: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.profileForm = this.fb.group({
      registrant: ['currentUser', Validators.required],
      guestInfo: this.fb.group({
        firstName: ['', this.guestInfoValidators],
        lastName: ['', ],
        badgeId: ['', ],
      }),
    });

    this.profileForm.get('registrant').valueChanges.subscribe((value) => {
      console.log(value);
      if (value === 'guest') {
        this.profileForm
          .get('guestInfo.firstName')
          .setValidators(this.guestInfoValidators.concat(Validators.required));
      } else {
        this.profileForm
          .get('guestInfo.firstName')
          .setValidators(this.guestInfoValidators.concat());
      }
    });
  }
}

这里是HTML:

<form [formGroup]="profileForm">
  <div>
    <input type="radio" 
    value="currentUser" 
    formControlName='registrant' 
    value='currentUser'
    id="currentUser"
    />
    <label for="currentUser">Register Myself</label>
  </div>
  <div>
    <input type="radio"  
    formControlName='registrant' 
    value="guest" 
    id="guest"
    />
    <label for="guest">Register Guest</label>
  </div>
  
  <div *ngIf="profileForm.get('registrant')?.value=='guest'">
  <div formGroupName = 'guestInfo' class="guestData">
  <label for="firstName">First Name</label>
   <input id="firstName" type="text" formControlName="firstName">

   <label for="lastName">Last Name</label>
   <input id="lastName" type="text" formControlName="lastName">

   <label for="badgeId">Badge</label>
   <input type="text" id="badgeId" formControlName="badgeId">
 </div>
  </div>
</form>

在我的控制台中出现此错误:

ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'VALID'. Current value: 'INVALID'.. Find more at https://angular.io/errors/NG0100
    at throwErrorIfNoChangesMode (errors.ts:63:9)
    at bindingUpdated (bindings.ts:72:12)
    at interpolation1 (interpolation.ts:74:21)
    at Object.ɵɵtextInterpolate1 (text_interpolation.ts:93:24)
    at AppComponent_Template (app.component.html:41:4)
    at executeTemplate (shared.ts:528:1)
    at refreshView (shared.ts:381:62)
    at refreshComponent (shared.ts:1732:1)
    at refreshChildComponents (shared.ts:129:3)
    at refreshView (shared.ts:435:6)

我是 Angular 的新手,如果您能告诉我我做错了什么,我将不胜感激。

ngOnInit() {
    this.profileForm = this.fb.group({
      registrant: ['currentUser', Validators.required],
      guestInfo: this.fb.group(
        {
          firstName: [''],
          lastName: [''],
          badgeId: [''],
        },
      ),
    });

    this.profileForm.get('registrant').valueChanges.subscribe((value) => {
      console.log(value);
      debugger;
      if (value === 'guest') {
        this.profileForm
          .get('guestInfo.firstName')
          .setValidators([Validators.required]);
        this.profileForm.get('guestInfo.firstName').updateValueAndValidity();
      } else {
        this.profileForm.get('guestInfo.firstName').clearValidators();
        this.profileForm.get('guestInfo.firstName').updateValueAndValidity();
      }
    });
}

要清理您的代码,请尝试制作您自己的验证函数

   
function RequiredIfGuest(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const isGuest = control.value === “guest”
    return isGuest ? {required: true} : null;
  };
}

所以制作你的表单,使用验证器

  registrant: ['currentUser', RequiredIfGuest()]
  

抱歉,如果有语法错误,我在移动设备上