2

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

3
  • why that way does not work ? Commented Oct 20, 2017 at 15:11
  • the .getValidators () method does not exist in Angular 2 - 4, or at least I have not found something similar. However, if a .setValidators () method exists in Angular 2 - 4. Commented Oct 20, 2017 at 15:22
  • check my answer Commented Oct 20, 2017 at 15:46

2 Answers 2

2

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 :)

Sign up to request clarification or add additional context in comments.

7 Comments

thanks for your reply. let validators = this.myForm.controls[key].validator(''); this returns the validators?
is there any errors ? works it ? @RidelHernándezInfante
It does not work, let validators = this.myForm.controls [key] .validator (''); throws the following error: Error: (72, 107) TS2345: Argument of type '' is not assignable to parameter of type 'AbstractControl'. I do not think it returns the validators
it accepts an AbstractControl as parameter , i updated the answer try it now
after updating your code is happening as follows: let validators = this.myForm.controls [key] .validator (this.myForm.controls [key]) get the value correctly ({required: true}) when the validator is "required" but when it is another for example "min" returns null
|
0

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);
    }
  }
}

3 Comments

thanks for your reply, I will try to optimize once you have the solution in the field of angular, thanks
Not implemented yet. but u can see for github.com/angular/angular/issues/13461
By the way, I will not recommend using push(mutate state). It's hard to manage state. Did some modification, maybe u can try something like this as clean code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.