0
votes

I have an angular reactive form with default Validation.required and a CustomValidation. Inside the CustomValidation I intended to check if the control is touched, but somehow this is not working.

import {
  CustomValidation
} from './CustomValidator';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  customForm: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.customForm = this.fb.group({
      customInput: [
        '', [Validators.required, CustomValidation.customEmailValidation()],
      ],
    });
  }
}



// CustomValidation.ts

import {
  AbstractControl,
  ValidationErrors,
  ValidatorFn
} from '@angular/forms';

export class CustomValidation {
  static customEmailValidation(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      if (control.touched && control.value.length === 0) {
        console.log(control);
        return {
          customError: {
            hasError: true,
            errorType: 'empty field', // this can be any name
            errorLabel: 'test',
          },
        };
      }
      return null;
    };
  }
}
<form [formGroup]="customForm">
  <input formControlName="customInput" />
  <button [disabled]="this.customForm.invalid">Submit</button>
</form>

I am expecting that the console.log inside the static method customEmailValidation will log the control object when the field will be touched. By touch I mean, I only click on the input.But that is not happening.

I also tried using updateOn

customInput: ['', {validators:[CustomValidation.customEmailValidation(),Validators.required],updateOn:"blur"}]

Please help me in understanding why it is not working.

Stackblitz Demo

2
validation doesn't trigger on touch. it triggers when the value changes (or on blur/submit if you use the updateOn blur/submit option). there isn't an update on touch option, as it's not really clear how that option would even work. I'd remove that from the validator and instead just check if the form control has been touched when deciding to show / hide my error state.bryan60

2 Answers

0
votes

At first, before you touch it, form.touched is false. So thats the first value.

That value is being taken for the first time as form.touched

So you will get touched property as false.

If you intend to make it touched, just go with this.form.markAsTouched() and then do the logic.

0
votes

You are describing the onfocus event, not the touched state.

From the Angular docs:

touched: boolean Read-Only True if the control is marked as touched.

A control is marked touched once the user has triggered a blur event on it.

You are expecting this:

By touch I mean, I only click on the input.But that is not happening.

Also, the custom validator should be agnostic to the form input state. You can achieve what you want by binding to the onfocus event. I don't understand why you would want to do this from a UX perspective, but hey.

Template

<form (focusin)="onFocusIn($event)" [formGroup]="customForm">
  <input formControlName="customInput" />
  <button [disabled]="this.customForm.invalid">Submit</button>
</form>
<span *ngIf="this.customForm.invalid && this.customForm.touched"
  >VERY SERIOUS ERROR</span
>

Component

  onFocusIn(event) {
    this.customForm.markAsTouched();
    console.log('focus');
  }

Validator

  static customEmailValidation(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      if (control.value.length === 0) {
        console.log(control);
        return {
          // ...control.errors,
          customError: {
            hasError: true,
            errorType: 'empty field', // this can be any name
            errorLabel: 'test',
          },
        };
      }
      return null;
    };
  }

Stackblitz here.

You can read more about custom form controls here from the Angular docs.