Corey Witherow
Corey Witherow

Reputation: 2472

reactive forms setValidator and updateOn

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

Answers (5)

Newclique
Newclique

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

Lin
Lin

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

Phuc Lee
Phuc Lee

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

Adam Marshall
Adam Marshall

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

Franklin Pious
Franklin Pious

Reputation: 3848

Example showing dynamic validation

this.form.get('company_name').setValidators(Validators.compose([Validators.required, Validators.maxLength(45)]));      


this.form.updateValueAndValidity();

Upvotes: 1

Related Questions