4

I have reactive form and don't want validation to be triggered until user really visits a field.

For example, this is a field:

<input type="text" [formControl]="customerNumber">

And this is the component:

customerNumber: FormControl = new FormControl(
    null, {validators: [Validators.required]
});

As you see, its simple. The issue I have is that validation is triggered when the form is displayed and the input field gets ng-invalid class, even it is not touched.

I need validation to be triggered only after the user touches the field.

3
  • I am aware that in Angular 1.5 whilst validating you could check for input.$touched But, I'm not familiar with Angular 2's syntax. It might be worth checking out the NG2 validation docs angular.io/guide/form-validation Commented Feb 9, 2018 at 15:36
  • @FrancisLeigh I can check if the field is touched, but I do not need that. I want validation engine to not validate the field if it is not touched. In other words, I want Angular2 to check that, not me. Commented Feb 9, 2018 at 15:37
  • 1
    So basically you want the field to be optional until the user touches it. So you should begin by removing Validators.required from the initial configuration. Then you listen to an event that gets triggered when you touch the field, and programmatically set the field to be required. Sounds like it should be possible, but I dont know the available options. You could console log the form to see what methods and events are available to achieve this. Commented Feb 9, 2018 at 15:54

1 Answer 1

2

As somebody mentioned in the comments:

Initial config:

customerNumber: FormControl = new FormControl(null);

Subscribe to value changes and set your validator only if a validator is not already set:

this.sub = this.form.controls.customerNumber.valueChanges.subscribe(value => {
   if (!this.form.controls.customerNumber.validator) {  
       this.form.controls.customerNumber.setValidators(Validators.required);
   }
})

If you need to perform validation on the value that triggered validator setup make sure to call:

this.form.controls.customerNumber.updateValueAndValidity();

immediately after the setup.

Also, make sure to unsubscribe once you are done with the component:

ngOnDestroy() {
    this.sub.usubscribe();
}    

EDIT

Another option would be to create a custom required validator that validates only if the control is dirty.:

import { FormControl } from '@angular/forms';

function customRequiredValidator(c: FormControl) {
    if(!c.dirty)
    {
      return null;
    }
    ...
}

You can then just import it wherever needed and use it in place of the Validators.required.

Sign up to request clarification or add additional context in comments.

7 Comments

And I have to do this for every component I have? :(
There are other options. You could write your custom required validator that checks for dirty and than reuse that across your app instead of the Validators.required. Or you could simply expand the *ngIf condition in your template so that you do not show a validation error in case the control is not dirty. Here's a stackblitz example stackblitz.com/edit/angular-uhjydn
You do not want to have a empty required field having a valid state just because the user didn't touch it.
could you add the idea about custom Validators in the Answer? For me, that is the way to go. I have a set of custom validators that first check if a value is untouched or if it is null - and then validate only if initial value changes, meaning component was touched. This is for me very clean way.
for the record, I can't believe this common UX case is not covered by Angular. Sorry for ranting, but I hate hacking frameworks.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.