1

The official Angular docs have a dynamic form tutorial containing a story for dynamic forms. A service is used to create the FormGroup object like so:

    toFormGroup(questions: QuestionBase<any>[] ) {
    let group: any = {};

    questions.forEach(question => {
      group[question.key] = question.required ? new FormControl(question.value || '', Validators.required)
                                              : new FormControl(question.value || '');
    });
    return new FormGroup(group);
  }

How can I add more than one validator function to each FormControl object? The following doesn't seem to work:

questions.forEach(question => {
      group[question.key] = question.required ? new FormControl(question.value || '', [Validators.required, Validators.maxLength(12)])
                                              : new FormControl(question.value || '');
    });

I've also tried Validators.compose([Validators.required, Validators.maxLength(12)]) which doesn't work as expected either. The only validator that seems to be applied is the 'required' validator. Here is a plnkr demonstrating the behavior. The code mentioned above is contained in the question-control.service.ts file.

The expected outcome i'm trying to achieve is to have the maxLength validator also applied to the FirstName control.

2
  • @Vega The code is directly from the angular.io site. Only modifications that were made was adding an array of validators to the second param of the FormControl constructor Commented Jul 21, 2017 at 19:24
  • the validator works in your plunkr... What are you expecting as result? Commented Jul 21, 2017 at 19:34

2 Answers 2

3

The validations are actually in place, but currently you just have a generic check if the field is not valid or not:

<div class="errorMessage" *ngIf="!isValid">{{question.label}} is required</div>

That will of course display this message if the field is not valid.

The quick solution is to check which error field has:

<div class="errorMessage" *ngIf="form.controls[question.key].hasError('required')">
   {{question.label}} is required
</div>
<div class="errorMessage" *ngIf="form.controls[question.key].hasError('maxlength')">
   {{question.label}} is too long
</div>

plunker: https://plnkr.co/edit/RQRQiJfQbnOHEPuS0jji?p=preview

But since your form is dynamic, I guess you also want a validation that is as dynamic as possible. For that I suggest you take a look at this sample from the official docs which are using an object formErrors and validationMessages with all validation messages stored, and then using these together with this method whenever there are changes in the form:

onValueChanged(data?: any) {
  if (!this.heroForm) { return; }
  const form = this.heroForm;

  for (const field in this.formErrors) {
    // clear previous error message (if any)
    this.formErrors[field] = '';
    const control = form.get(field);

    if (control && control.dirty && !control.valid) {
      const messages = this.validationMessages[field];
      for (const key in control.errors) {
        this.formErrors[field] += messages[key] + ' ';
      }
    }
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Validation doesn't appear to be in place, because form is valid on the first character input
I don't know... here it at least shows form is not valid if the name is too long: plnkr.co/edit/n5Y6Z0UCwjSd3ZfRfvvK?p=preview
You had validator for maxlength not minlength, is that what's confusing?
Consequence of staring at screen to long. Your right. Thanks for your help.
Happens to all of us ;) Glad I could help, have a nice weekend Mike, and happy coding, but remember to rest your eyes and brain for a while in between :P
0

What you can do is place the necessary validations for each question in an array, I did it this way:

toFormGroup(questions: QuestionBase<any>[] ) {
    const group: any = {};
    let validaciones = [];
    questions.forEach(question => {
      if (question.required) {
        validaciones.push(Validators.required);
      }
      // Validación para solo números
      if (question.number) {
        validaciones.push(Validators.pattern(/^([0-9])*$/));
      }

      group[question.key] = new FormControl(question.value || '', validaciones);
      validaciones = [];

    });

I leave my repository on GitHub if you want to take a look https://github.com/aleRozo/formulariosDinamicos/

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.