I have an Angular form where the following validation should happen:
checkbox === ticked then validate the input else no validation
checkbox === unticked then no validation but rechecking should enable the validation
I am having issues when on the page load the checkbox is unticked and the input box does not have any value the validation doesn't trigger which is expected. However, the input box validation doesn't trigger immediately after clicking the checkbox when the input is empty.
Here is the code:
private myFormValidator(predicate: Function, validator: ValidatorFn): ValidatorFn {
return ((formControl: FormControl) => {
if (!formControl.parent) {
return null;
}
let error = null;
if (predicate()) {
console.log('predicate()');
return validator(formControl);
}
return null;
});
}
this.partnerInvoiceDetailsForm = this.fb.group(
{
rebates: new FormGroup({
territories: new FormGroup({
rebateTier: new FormControl(null, [
this.myFormValidator(() => this.rebateActive(this.rebateIdMap[1]).value, Validators.required)]),
rebateValue: new FormControl(null),
rebateActive: new FormControl(null)
})
}
);
// console.log(this.partnerInvoiceDetailsForm.get('rebates.territories.rebateTier'));
this.partnerInvoiceDetailsForm.get('rebates.territories.rebateActive')
.valueChanges
.subscribe(value => {
console.log(value)
this.partnerInvoiceDetailsForm.get('rebates.territories.rebateTier').updateValueAndValidity();
});
CodePudding user response:
Approach 1: With valueChanges
observable
During the "rebates.territories.rebateActive" value change event, you can add the validator programmatically via addValidators
and removeValidators
methods. Note that you have to pass the same reference for the validator function added into validators in order to remove it correctly.
const myFormValidator = this.myFormValidator(
() => this.rebateActive(this.rebateIdMap[1]).value,
Validators.required
);
this.partnerInvoiceDetailsForm
.get('rebates.territories.rebateActive')
.valueChanges.subscribe((value) => {
console.log(value);
if (value)
this.partnerInvoiceDetailsForm
.get('rebates.territories.rebateTier')
.addValidators(myFormValidator);
else
this.partnerInvoiceDetailsForm
.get('rebates.territories.rebateTier')
.removeValidators(myFormValidator);
this.partnerInvoiceDetailsForm
.get('rebates.territories.rebateTier')
.updateValueAndValidity();
});
Approach 2: Modify myFormValidator
ValidatorFn by adding dependency
parameter.
If you allow to modify the myFormValidator
, you can add dependency
parameter and implement the logic to check the value of dependency
to proceed/exit the logic.
private myFormValidator(
predicate: Function,
dependency: string,
validator: ValidatorFn
): ValidatorFn {
return (formControl: FormControl) => {
if (!formControl.parent) {
return null;
}
if (!formControl.parent.get(dependency)?.value) return null;
let error = null;
if (predicate()) {
console.log('predicate()');
return validator(formControl);
}
return null;
};
}
The key point of implementing this approach is you have to trigger this.partnerInvoiceDetailsForm.get('rebates.territories.rebateTier').updateValueAndValidity()
when the rebates.territories.rebateActive
's value is changed.
ngOnInit() {
this.partnerInvoiceDetailsForm = this.fb.group({
rebates: new FormGroup({
territories: new FormGroup({
rebateTier: new FormControl(null, [
this.myFormValidator(
() => this.rebateActive(this.rebateIdMap[1]).value,
'rebateActive',
Validators.required
),
]),
rebateValue: new FormControl(null),
rebateActive: new FormControl(null),
}),
}),
});
this.partnerInvoiceDetailsForm
.get('rebates.territories.rebateActive')
.valueChanges.subscribe((value) => {
console.log(value);
this.partnerInvoiceDetailsForm
.get('rebates.territories.rebateTier')
.updateValueAndValidity();
});
}