How to Add a Validator dynamically to a FormControl in Angular 2

25,802

Looking at your code, what you could do:

<div class="form-group" [ngClass]="{'has-danger':!form.get('site_id').valid}">
        <label for="site_id" class="form-control-label">Site</label>
        <input id="site_id" [formControl]="site_id_control" type="text" placeholder="Site" class="form-control input-sm">
        <div *ngIf="!form.get('site_id').valid">
            <div class="form-control-feedback">Site is required?</div>
            <small class="form-text text-muted">Please enter a Site, eg. xyz.</small>
        </div>
    </div>

Look at [formControl]="site_id_control"

Then, this way, you can add or remove the validators from that specific control like this:

inside your class:

export class JobSearchEditComponent {
    private site_id_control=this.form.controls['site_id'];

    updateValidator(){
       let exisitingValidators = this.site_id_control.validators;
       this.site_id_control.setValidators(Validators.compose([...existingValidators , exampleValidator]))

        // you probably also need this : 
         this.site_id_control.updateValueAndValidity();

    }
}
Share:
25,802
David Cruwys
Author by

David Cruwys

I’m a Nerd and a bit of a futurist who loves exploring the interrelationship of human to human connection and AI/machine learning whilst keeping up to date on technology trends, especially those related to online commerce and marketing. ♦ Cloud Application Development expertise that includes Scalable commercial web-sites, Real-time cloud quotation engines, data mining and artificial intelligence systems using .NET, Rails, Python and Angular Technology.

Updated on July 09, 2022

Comments

  • David Cruwys
    David Cruwys almost 2 years

    I am using ReactiveFormsModule and have defined all my form controls including simple validators such as Validators.required within a const configuration.

    I wanted to add a custom validator to one of those FormControls.

    I have currently added the custom validator as a function within this configuration, and it is working fine, but it does not belong here, it really needs to live within my component, but I'm not sure how I can just attach a custom validator manually after the FormBuilder has configured all my controls.

    See Code Comment below that looks like this

    How do I Attach Here

    * ??? *

    this.form.get('site_id').add custom valiator

    This is my current configuration code.

    import {FormControl, Validators, FormBuilder} from '@angular/forms';
    
    var fb = new FormBuilder();
    
    function exampleValidator(control: FormControl): { [s: string]: boolean} {
        if (control.value === 'Example'){
            return { example: true };
        }
    
        return null;
    }
    
    export const formConfig = fb.group({
      'extract_batch_id': ['bbbbbbbbbbbbb',
        [
           Validators.required
        ]], 
      'site_id': ['blah',
        [
           Validators.required,
            exampleValidator
        ]]
    });
    

    I have a directive that really should be storing the custom validator

    Job Search Component

    import {Component, Input, OnInit, OnDestroy} from '@angular/core';
    import {FormGroup, FormControl} from '@angular/forms';
    import {ActivatedRoute} from '@angular/router';
    import {Subscription} from 'rxjs';
    
    import {Job} from '../../../models/job';
    import {JobService} from '../../../services/api/job.service';
    import {DebugService} from '../../../common/debug/debug.service';
    import {formConfig} from './edit.form-config';
    
    @Component({
        selector: 'wk-job-search-edit',
        template: require('./edit.html')
    })
    export class JobSearchEditComponent {
        form: FormGroup;
    
        job: Job;
    
        @Input() jobId: number;
        private subscription: Subscription;
    
        constructor(
            private route: ActivatedRoute,
            private jobService: JobService,
            private debug: DebugService){
    
            // Configure form FormGroup via exported formConfig
            this.form = formConfig;
    
            // How do I Attach Here
            // *** ??? ***
            // this.form.get('site_id').add custom valiator 
        }
    
        /*
        exampleValidator(control: FormControl): { [s: string]: boolean} {
            if (control.value === 'Example'){
                return { example: true };
            }
    
            return null;
        }
        */
    }
    

    JobSearch Edit.html

    <form [formGroup]="form" (ngSubmit)="onSubmit()">
    
        <button type="submit" class="btn btn-success" [disabled]="!form.valid">Save</button>
        <div class="form-group" [ngClass]="{'has-danger':!form.get('extract_batch_id').valid}">
            <label for="extract_batch_id" class="form-control-label">Extract Batch</label>
            <input id="extract_batch_id" formControlName="extract_batch_id" type="text" placeholder="Extract Batch" class="form-control input-sm">
            <div *ngIf="!form.get('extract_batch_id').valid">
                <div class="form-control-feedback">Extract Batch is required?</div>
                <small class="form-text text-muted">Please enter a Extract Batch, eg. xyz.</small>
            </div>
        </div>
    
        <div class="form-group" [ngClass]="{'has-danger':!form.get('site_id').valid}">
            <label for="site_id" class="form-control-label">Site</label>
            <input id="site_id" formControlName="site_id" type="text" placeholder="Site" class="form-control input-sm">
            <div *ngIf="!form.get('site_id').valid">
                <div class="form-control-feedback">Site is required?</div>
                <small class="form-text text-muted">Please enter a Site, eg. xyz.</small>
            </div>
        </div>
    
    
    </form>
    
  • David Cruwys
    David Cruwys over 7 years
    I will try that out and let you know how it goes
  • fidev
    fidev almost 7 years
    @DavidCruwys any progress on this?
  • jcairney
    jcairney almost 6 years
    This doesn't quite work (anymore?) as .validators is not (or no longer) a property of FormControl. It looks like all the validators added via the constructor get merged into one function. Though you could still do this.site_id_control.setValidators(Validators.compose([this.‌​site_id_control.vali‌​dator, exampleValidator])) without the spread.