In one of my Angular 7 form, i am trying to make input fields based on other user input values. This is my html code.
div>
<form [formGroup]="UserForm" #UserAdd="ngForm">
<mat-form-field>
<mat-label>Gender</mat-label>
<mat-select [(value)]="gentype" [formControl]="gendertype" required>
<mat-option value="Male">Male</mat-option>
<mat-option value="Female">Female</mat-option>
</mat-select>
<mat-error *ngIf="gendertype.hasError('required')">
Gender is required.
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Enrolled</mat-label>
<mat-select [(value)]="enrol" [formControl]="enrolled" required>
<mat-option value="No">No</mat-option>
<mat-option value="Yes">Yes</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="form-element" *ngIf="enrol=='Yes'">
<mat-label>User Preference</mat-label>
<input matInput [placeholder]="gentype=='Male' ? 'Chicago' : 'Milan'" formControlName="preference" [required]="true" autocomplete="off">
<mat-error *ngIf="preference.touched && !preference.required">
Preference is required.
</mat-error>
</mat-form-field>
</form>
<button mat-raised-button color="primary" type="button" (click)="Save();"[disabled]="!UserAdd.form.valid">SAVE</button>
</div>
Component.ts code.
private UserForm: FormGroup;
ngOnInit() {
this.createForm()
}
createForm() {
console.log('in createForm')
this.UserForm = new FormGroup({
gendertype: new FormControl(),
enrolled: new FormControl('No'),
preference: new FormControl('')
})
}
get gendertype() { return this.UserForm.get('gendertype') }
get enrolled() { return this.UserForm.get('enrolled') }
get preference() { return this.UserForm.get('preference') }
Problem here I am facing , when user select "enrol-No" the form is in invalid state and SAVE button is disabled. i want to make preference input as "required" when taken. And if user select "enrol-Yes", i get error
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'disabled: false'. Current value: 'disabled: true'.
Please suggest , where i am wrong and good way to handle the scenario.
You are getting this error because you have required attribute binding on preference form control. When using reactive form you have to use validators functions to include validation to form control.
You can use disable property on FormControl to disable and enable formControl dynamically.
component.ts
createForm() {
console.log('in createForm')
this.UserForm = new FormGroup({
gendertype: new FormControl(),
enrolled: new FormControl('No'),
preference: new FormControl({value: '', disabled:true}, Validators.required)
})
}
In template side you can check wheather user enrolled or not, using entrolled control value property
component.html
<mat-form-field class="form-element" *ngIf="enrolled.value=='Yes'">
<mat-label>User Preference</mat-label>
<input matInput [placeholder]="gentype=='Male' ? 'Chicago' : 'Milan'" formControlName="preference" autocomplete="off">
<mat-error *ngIf="preference.touched && !preference.required">
Preference is required.
</mat-error>
</mat-form-field>
Finally listen valueChanges on enrolled control to disable and enable preference form control dyanmically
component.ts
this.createForm();
(this.enrolled as FormControl).valueChanges.subscribe(hasEntrolled=>{
if(hasEntrolled === 'Yes'){
(this.preference as FormControl).enable();
}else{
(this.preference as FormControl).disable();
}
});