3

Is it possible to compare a form field's input to a List using custom validators? I am NOT trying to compare two Form Controls to each other.

I have been trying with this approach:

this.formGroupName = this.formBuilder.group({
    category: ['', Validators.compose([Validators.required, this.checkCategoryInput(
      this.formGroupName.get['category'].value, this.categoryList)])]
});

where in the checkCategoryInput() method I will compare the value of the 'category' form control to a list of acceptable categories.

public checkCategoryInput(input: string, categoryList: any[]): {[key: string]: boolean} | null{
  console.log(input);
  console.log(categoryList);
  return null;
}

However I am getting lost in the syntax and getting a few errors trying to do it with this approach. Does anyone have a better way to compare form control values to a list???

masu9
  • 491
  • 8
  • 22
  • What errors are you getting? And where is the comparison that you are doing? Do you mean, you want to check if formcontrol value exists within a list? – Amit Chigadani Dec 12 '18 at 17:00
  • Did you ever get this working @masu9? – Ben Racicot Feb 15 '19 at 12:36
  • 2
    @TR3B Hello, yes I did - however I went with a different approach. I found it easier to subscribe to the valueChanges property of the form control, and to then manually set the errors myself using .setErrors({ 'invalid': true }); for example. You can check out this post here: https://stackoverflow.com/questions/43553544/how-can-i-manually-set-an-angular-form-field-as-invalid – masu9 Feb 15 '19 at 14:53

1 Answers1

5

You're close, and you're right; the syntax is a bit confusing. The custom Validator is expected to be a ValidatorFn method that will be called with a parameter of AbstractControl. For example, here's a very basic validator:

public static numeric(control: AbstractControl): { [key: string]: any } {
    return /^[0-9]+$/.test(control.value) ? null : { 'numeric': false };
}

// .. { category: [0, Validators.required, numeric] }

We just pass a reference of the method to the FormBuilder, which it will call passing the FormControl it's on to validate the value.

If you want to wrap up some of your own parameters with the validator, just create your own function scope and return a new method:

public static checkCategoryInput(input: string, categoryList: any[]): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } => {
        const val = control.value;
        return 'Do stuff with the value because `input` and `categoryList` are now in scope!'
    }
}

Just as a little extra info, since it's also not really stated well anywhere; the return signature of { [key: string]: boolean } | null is what will be put on the errors property of the ngControl, so usually you return null if it's valid and errorName: false if invalid. It's something to keep in mind if you're trying to show error messages based off this particular validator.

joh04667
  • 7,159
  • 27
  • 34
  • Thank you so much for the response. I'm just getting one last error that I'm hoping you can assist with. I am getting the error: `Cannot read property of 'get' of undefined`. I believe this is because of how I pass my category control value into the parameter. Can you see anything wrong in my syntax there? (My first code snippet in my question) – masu9 Dec 13 '18 at 14:15