Search code examples
angularformbuilder

How do you validate a FormBuilder control based on another in Angular2?


I'm using FormBuilder in Angular2 and I created a custom validator service.

Component

this.exampleForm  = this.formBuilder.group({
    'FirstName': ['', Validators.required],
    'LastName': ['', [Validators.required]],
    'Description': [''],
    'Location': [''],
});

this.exampleForm .addControl("StartDate", this.formBuilder.group({
    'Month': [0, [Validators.required, ValidationService.monthValidator]],
    'Year': [0, [Validators.required, ValidationService.yearValidator]]
}));

this.exampleForm .addControl("EndDate", this.formBuilder.group({
    'Month': [0],
    'Year': [0]
}));

HTML component

<div formGroupName="StartDate">
    <select formControlName="Month">
        <option>...</option>
        </option>
    </select>
    <select formControlName="Year">
        <option>...</option>
    </select>
</div>

I don't want to have an earlier EndDate than StartDate

How do I validate EndDate control based on StarDate control?

EDIT

Tried something like this:

this.exampleForm  = this.formBuilder.group({
        ...
    }, passwordMatchValidator);

function passwordMatchValidator(g: FormGroup) {
   return g.get('FirstName').value === g.get('LastName').value
      ? null : {'mismatch': true};
}

It doesn't do anythig


Solution

  • You should group your two control in a FormGroup and test if this FormGroup is valid https://angular.io/docs/ts/latest/api/forms/index/FormGroup-class.html

    EDIT

    By default, a formgroup is valid if every FormControl are valid. You can define a custome validator for a FormGroup as you do for a FormControl. In this example, I added a validator (passwordMatchValidator) to the FormGroup containing two FormControl.

    stackoverflow-form.component.ts

    import { Component, OnInit } from '@angular/core';
    import { FormGroup, FormControl, FormBuilder } from '@angular/forms';
    
    @Component({
        selector: 'stackoverflow-form',
        templateUrl: 'stackoverflow-form.component.html',
        styleUrls: [
            'stackoverflow-form.component.css'
        ],
        providers: []
    })
    export class StackOverflowFormComponent implements OnInit {
        public myForm: FormGroup;
        public alphaCtrl: FormControl;
        public betaCtrl: FormControl;
    
        constructor(fb: FormBuilder) {
            this.alphaCtrl = fb.control('alphaValue', [StackOverflowFormComponent.myControlValidator]);
            this.betaCtrl = fb.control('betaValue', [StackOverflowFormComponent.myControlValidator]);
            this.myForm = new FormGroup({
                alpha: this.alphaCtrl,
                beta: this.betaCtrl,
            }, StackOverflowFormComponent.passwordMatchValidator);
        }
    
        // Custom FormControl Validator 
        static myControlValidator(control: FormControl) {
            return control.value.length > 1 ? null : { myInvalid: true};
        }
    
        // Custom FormGroup Validator 
        static passwordMatchValidator(g: FormGroup) {
            return g.get('alpha').value === g.get('beta').value
                ? null : {'mismatch': true};
        }
    
        ngOnInit() {}
    }
    

    stackoverflow-form.component.html

    <form (ngSubmit)="onSubmit()" [formGroup]="myForm">
        <input formControlName="alpha" name="alpha"/>
        <input formControlName="beta" name="beta"/>
        <button type="submit" [disabled]="!myForm.valid">SEND</button>
    </form>
    

    stackoverflow-form.component.css

    input.ng-invalid {
        background-color: red;
    }
    
    input.ng-valid {
        background-color: greenyellow;
    }