Search code examples
angularangular-reactive-forms

How to use Angular validators to invalidate a given value in form control?


I have an angular reactive form in which one of the select fields is pre selected.
The pre selected value is not null, and it can't be null because the way this value is used in other components. In some instances I would like the form to be invalid in case the default value is stil selected. I imagine there must be a way to achieve this with validators in a similar way as the nonNullable validator, except that in this case is a given value ("not-allowed") and not null.

Here my form.ts:

import { Component } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

@Component({
  selector: 'app-my-form',
  templateUrl: './my-form.component.html',
  styleUrls: ['./my-form.component.css'],
})
export class MyFormComponent {
  public myForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {
    this.myForm = this.formBuilder.group({
      username: this.formBuilder.control('', [Validators.required]),
      favouriteFood: this.formBuilder.control('not-allowed', [
        Validators.required,
      ]),
      password: this.formBuilder.control('', [Validators.required]),
    });
  }

  public save(): void {
    if (this.myForm.valid) {
      console.log('submited');
    } else {
      console.error('invalid');
    }
  }
}

And html:

<form [formGroup]="myForm" (ngSubmit)="save()">
  <label>Username:</label>
  <input type="text" formControlName="username" />

  <div>
    <label>Favorite food</label>
    <select name="cars" id="cars" formControlName="favouriteFood">
      <option value="not-allowed">Please Select</option>
      <option value="steak-0">Steak</option>
      <option value="pizza-1">Pizza</option>
      <option value="tacos-2">Tacos</option>
    </select>
  </div>
  <label>Password:</label>
  <input type="password" formControlName="password" />

  <button type="submit">Submit</button>
</form>

And the link to a fiddle:
https://stackblitz.com/edit/angular-elements-fiddle-dwhmc8?file=src%2Fapp%2Fapp.component.ts

I would like to the form to not be valid while "Please Select" option is still selected.


Solution

  • You can create a custom ValidatorFn that checks the value of your control:

    favouriteFood: this.formBuilder.control('not-allowed', [
      Validators.required,
      (control: AbstractControl) => {
        return control.value === 'not-allowed'
          ? { favoriteFood: true }
          : null;
        },
    ]),
    

    The shape is (AbstractControl): ValidationErrors | null so, if you find an error, you have to return a ValidationErrors object with the key of the field you want to mark as invalid.