Home > Software design >  How do I conditionally validate input fields in my reactive form?
How do I conditionally validate input fields in my reactive form?

Time:02-16

I have a form where a user can register thesmselves or a guest. If a user is registering themselves, I don't need to validate guest info input fields, and I do need to do it if a guest is being registered by a user. This is the link to stackblitz.

Here is a simplified example of my reactive form with validation that is not working correctly:

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());
      }
    });
  }
}

Here is 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' >
  <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>

In my console I get this error:

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)

I'm very new to Angular, and I'd appreciate if you could tell me what I'm doing wrong.

CodePudding user response:

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();
  }
});

}

CodePudding user response:

To clean up your code, try making your own validation function

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

So making your form, use the validator

  registrant: ['currentUser', RequiredIfGuest()]
  

Sorry if there’s a syntax error, I’m on mobile

  • Related