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