i'm using angular Reactive Forms with Form Validations. I would like to create a select input, and only if a specific option is selected ('Other') I want to show additional text input (so user can enter custom answer).
I made the text input not required by default, then onValueChanged
i'm checking if option is 'Other' and use setValidators
to change the input to required.This seem to work, but i'm getting this error:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.
Here is my code:
component.ts
buildForm() {
this.validationForm = this.formBuilder.group({
PaymentMethod: this.formBuilder.control(null, [Validators.required]),
Package: this.formBuilder.control(null, [Validators.required]),
CustomAmount: this.formBuilder.control(null, [Validators.min(50), Validators.max(400)]),
});
this.validationForm.valueChanges
.subscribe((data) => this.onValueChanged(data));
this.onValueChanged(); // (re)set validation messages now
}
onValueChanged(data?: any) {
if (data && data.Package && data.Package.Name === 'Other') {
console.log('amount should be required now');
this.validationForm.controls.CustomAmount.setValidators([Validators.min(50), Validators.max(400), Validators.required]);
}else {
this.validationForm.controls.CustomAmount.setValidators([Validators.min(50), Validators.max(400)]);
}
...
}
component.html
<form [formGroup]="validationForm" (ngSubmit)="onSubmit()" novalidate>
<div class="form-group">
<p>
<strong style="display: inline-block; width: 120px;">Payment Method</strong>
<md-radio-group class="md-radio-group-spacing" formControlName="PaymentMethod" [(ngModel)]="radio.group1">
<md-radio-button value="Cash">Cash</md-radio-button>
<md-radio-button value="Credit">Credit</md-radio-button>
</md-radio-group>
</p>
<p>
<md-select *ngIf="packages" placeholder="Choose Package" formControlName="Package" [(ngModel)]="selectedPackage">
<md-option *ngFor="let package of packages" [value]="package">
{{ package.Name }} <span class="blue-500"> {{ package.Price | currency:'USD':true }}</span>
</md-option>
</md-select>
</p>
<div *ngIf="selectedPackage" class="callout callout-info">
<strong>Selected:</strong> {{selectedPackage.Name}}
<p>{{selectedPackage.Description}}</p>
</div>
<div *ngIf="selectedPackage && selectedPackage.Name == 'Other'">
<div class="form-group">
<md-input-container class="full-width">
<input type="number" mdInput formControlName="CustomAmount" placeholder="Enter Amount">
</md-input-container>
<small *ngIf="formErrors.CustomAmount" class="red-500">
{{ formErrors.CustomAmount }}
</small>
</div>
</div>
</div>
<button md-raised-button type="submit" class="btn-w-md" color="primary" [disabled]="!validationForm.valid">Submit</button>
<span class="space space-md"></span>
<button md-raised-button type="button" class="btn-w-md" (click)="dialogRef.close('Cancel')">Cancel</button>
</form>
edit I found a solution here that is to enable/disable the input. works great! but i'm still happy to hear thoughts and other solutions you think are best. thanks