Reputation: 2472
I'm trying to set a validator on a formControl dynamically and can't seem to get the updateOn: "blur" to work properly. Instead of on blur it seems to be checking on change. Is there something special I need to do to get this to work on blur instead of on change.
this.form.get("deviceInfo").controls.deviceNumber.setValidators({validators: [Validators.required, this.checkDeviceExists()], updateOn: 'blur'});
added the updateValueAndValidity() but still fires on change instead of blur
var deviceInfo = this.form.get("deviceInfo");
deviceInfo.controls.deviceNumber.setValidators({validators: [Validators.required, this.checkDeviceExists()], updateOn: 'blur'});
deviceInfo.controls.deviceNumber.updateValueAndValidity();
Upvotes: 6
Views: 10766
Reputation: 494
I empathize with OP. I've found the Reactive form controls (v9) never validate the first time they are touched. If I have a required field that currently has a value in it, and the user clicks into the field, erases the value, and then tabs out, the invalid style elements are not applied (red outline, icon, etc.). They only appear at submit or if the user happens to click back into the field and then out again.
Here is my approach to get the validation to trigger immediately upon tabbing out of an invalid field which has never been touched before.
In my controller (note that I have two Reactive forms on the page):
blurMe(e){
let c = this.parentForm.controls[e.target.attributes['formControlName'].value];
if(!c)
c = this.childForm.controls[e.target.attributes['formControlName'].value];
if(c){
c.updateValueAndValidity({onlySelf:true,emitEvent:true});
}
}
On my view, I add a simple (blur) event binding to any control that needs to be immediately validated. (I am using the Clarity framework from vmWare, v3):
<input autocomplete="off" clrInput type="text" formControlName="badgeLabel" style="width:36em" (blur)="blurMe($event)" />
Upvotes: 0
Reputation: 11
this.form.setControl('deviceInfo',
new FormControl(this.form.controls['deviceInfo'].value,
{
validators:[Validators.required,],
updateOn: 'blur'
})
);
this.form.get('deviceInfo').updateValueAndValidity();
Upvotes: 1
Reputation: 29
I have the solotion this below :
Please add null validators when create FormControl for FormBulder :
taxCode: [null, { validators: null, updateOn: 'blur' }]
Then add new Validators with the condition :
this.editForm.get('taxCode').setValidators(Validators.compose([isTaxcode]));
Upvotes: 2
Reputation: 3009
Another technique is described in https://medium.com/@theykillimmortal/dynamically-changing-of-angular-updateon-option-and-validation-behavior-7acc7f93f357
The approach is to use setControl()
instead of setValidators()
, which allows construction of an entire control (including the all-important AbstractControlOptions
and updateOn
property).
e.g.
const oldControl = this.form.get('deviceInfo.deviceNumber');
const newControl = this.formBuilder.control(oldControl.value, {
validators: [Validators.required, this.checkDeviceExists()],
updateOn: 'blur'
});
this.form.setControl('deviceInfo.deviceNumber', newControl);
This seems overkill to me, in my opinion setValidators()
should allow passing an AbstractControlOptions
type.
Upvotes: 2
Reputation: 3848
Example showing dynamic validation
this.form.get('company_name').setValidators(Validators.compose([Validators.required, Validators.maxLength(45)]));
this.form.updateValueAndValidity();
Upvotes: 1