Search code examples
angularangular2-forms

Angular 2 Custom validator that depends on another form control


I'm trying to make a custom validator for my FormControl mealType

If my FormControl category has a value and mealType does not, mealType should be invalid.

If category has no value, mealType should be valid.

I'm getting a console error:

TypeError: Cannot read property 'get' of undefined

code:

ngOnInit() {
    this.findForm = this.formBuilder.group({
        categories: [null, Validators.required],
        mealTypes: [null, this.validateMealType],
        distanceNumber: null,
        distanceUnit: 'kilometers',
        keywords: null,
    });
}

validateMealType() {
    if (this.findForm.get('categories').value) {
        if (this.findForm.get('mealTypes').value) {
            var mealTypeError = false;
        } else {
            var mealTypeError = true;
        }
    } else {
        var mealTypeError = false;
    }

    return mealTypeError ? null : {
        error: true
    }
}

It is my form that is undefined.

How do I resolve this?

Trying this:

validateMealType(categoryControl: FormControl, mealTypeControl: FormControl) {
    if (categoryControl.value) {
        if (!mealTypeControl.value) {
            var mealTypeError = true;
        } else {
            var mealTypeError = false;
        }
    } else {
        var mealTypeError = false;
    }

    return mealTypeError ? null : {
        error: true
    }
}

but it causes:

Error in app/find-page/subcomponents/find-page/find-form.component.html:36:5 caused by: Cannot read property 'value' of undefined

trying this:

class MealTypeValidator {

    constructor(private categoryFormControl: FormControl) { }

    mealTypeValidator(control: FormControl): { [error: string]: any } {
        if (this.categoryFormControl.value) {
            if (!control.value) {
                return { error: true };
            }
        }
    }
}

then in my form component:

ngOnInit() {
    this.findForm = this.formBuilder.group({
        categories: [null, Validators.required],
        mealTypes: [null, new MealTypeValidator(this.findForm.get('categories').mealTypeValidator()],
        distanceNumber: null,
        distanceUnit: 'kilometers',
        keywords: null,
    });
}

but I have compilation errors. How do I get this right? I think i'm just a bit off on both the validation class I made and the usage of it.


Solution

  • You are one step closer.

    You need to attach your custom validator to the FormGroup instead, because it needs to know two FormControl (categories and mealTypes), so attaching to FormGroup will give the validator more broad view and access to the entire FormControl

    To achieve that, change your ngOnInit to

    ngOnInit() {
        this.findForm = new FormGroup({
            mealTypes : new FormControl(null, Validators.Required),
            categories : new FormControl(null)
            // others form control here
        }, validateMealType); // <-- see here is your custom function
    }
    

    On above code, you actually have to use FormGroup constructor instead of FormBuilder, so you can attach your custom validation in the parameters. Also, move your custom validator outside the component class.

    Take a look at this Plunker to get more insight for your specific case here.