How to dynamically add validators to the Forms in Angular 2 - 4 using FormBuilder?

I am using FormBuilder to build a form :

this.myForm = this.fb.group({
  'name': new FormControl(null, Validators.min(5)),
  'description': new FormControl(null, Validators.min(60))
});

The problem is I should also validate if it is required and I get it from configuration through a map built like this:

map = new Map<string, boolean>();
map.set('name', true);
map.set('description', false);

The problem can be solved as follows:

this.myForm = this.fb.group({
  'name': this.map.get('name') ? new FormControl(null, Validators.compose([Validators.required, Validators.min(5)])) : new FormControl(null, Validators.min(5)),
  'description': this.map.get('description') ? new FormControl(null, Validators.compose([Validators.required, Validators.min(60)])) : new FormControl(null, Validators.min(60))
});

That works but imagine in a large application with several forms with lots of fields really is uncomfortable this way of doing it. Ideally it would look something like this:

Object.keys(this.myForm.controls).forEach(key => {
  if (map.get(key)) {
    this.myForm.get(key).setValidators(this.myForm.get(key).getValidators().push(Validators.required))
  }
});

Of course that way does not work. So if someone who has already solved this or has a good way to do what is described above I will thank you very much. Thanks in advance!!!

Update: The problem can be reduced to "how to get all validators associated with a FormControl". I do not think there is a definitive solution to this question --> https://github.com/angular/angular/issues/13461

Upvotes: 2

Views: 1728

Answers (2)

xdeepakv
xdeepakv

Reputation: 8125

Just cleaned/refactor up above code. Create a composer function Please take look

// composer function
const composer = (control: FormControl, ...validators) => {
  control.setValidators(Validators.compose([...validators]));
}

for (let name of Object.keys(grp)) {
  let control = this.heroForm.controls[name];
  if (map.has(name)) {
    let validators = control.validator(control);
    if (validators && !validators.required) {
      let exisitingValidators = control.validators;
      composer(control, ...exisitingValidators, Validators.required);
    }
  }
}

Upvotes: 0

Mohamed Ali RACHID
Mohamed Ali RACHID

Reputation: 3297

here is a simple solution, i explained it in comments :

Object.keys(this.myForm.controls).forEach(key => {
        // if it needs to be required 
        if (map.get(key)) {
            // you have first to check if it already contains validator.required.
            let validators = this.myForm.controls[key].validator(this.myForm.controls[key]);
            // if it contains it -> {required: true};
            // if it doesn't contains it you can now add the required validator
            if(validators && !validators.required){
                let exisitingValidators = this.myForm.controls[key].validators;        
                this.myForm.controls[key].setValidators(Validators.compose([...existingValidators ,Validators.required]));
                // call updateValueAndValidity to apply the new validators on the control
                this.myForm.controls[key].updateValueAndValidity();                
        }
    });

Hope it helps :)

Upvotes: 2

Related Questions