0

Why is this form control error messages not showing I have an array and I'm reading it and generate dynamically questions. I can't find what is the mistake I have done in this code.

I have to show 4 error messages

  1. Required
  2. Min value validate
  3. Max value validate
  4. Unique value validate

I have an array which contains a question

questions: any = [{
      id: 13,
      surveyNo: 5,
      qNo: 3,
      question: 'Please rank the following features in order of importance,where 1 is the most important to you.?',
      qType: 3,
      noAnswrs: 4,
      answerType: 1,
      answers: ['Location', 'Confort', 'Service', 'Value for money']
    }];

I generated form controller dynamically likewise,

createForms(): any {
    this.surveyQuestionForm = this.fb.group(
      this.questions.reduce((group: any, question: { qNo: string; }) => {
        return Object.assign(group, { ['q' + question.qNo]: this.buildSubGroup(question) });
      }, {})
    );
  }

private buildSubGroup(question) {
    switch (question.qType) {
       case 3:
        return this.fb.group(
          question.answers.reduce((subGroup, answer) => {
            return Object.assign(subGroup, { [answer]: ['', [Validators.required, Validators.min(1), Validators.max(3)]] });
          }, {}), { validators: [this.uniqueNumbersValidator()] }
        );
        default:
        throw new Error('unhandled question type');
    }
  }

uniqueNumbersValidator() {
    return (ctrl: AbstractControl) => {
      const fg = ctrl as FormGroup;
      let allUnique = true;
      const values = [];
      Object.values(fg.controls).forEach(fc => {
        const val = fc.value;
        if (val && allUnique) {
          if (values.includes(val) && allUnique) {
            allUnique = false;
          }
          values.push(val);
        }
      });
      return (allUnique) ? null : { notAllUnique: true };
    };
  }

Here is my html code

<div class="form-group" formGroupName="{{'q' + question.qNo}}">
    <label class="control-label"> {{question.qNo}})
        {{question.question}}</label>
    <div class="ml-3">
        <table>
            <tr *ngFor="let anwr of question.answers; let a=index">
                <td>{{a+1}}. {{anwr}} </td>
                <div class="invalid-feedback"
                    *ngIf="surveyQuestionForm.get('q'+ question.qNo).touched 
                           && surveyQuestionForm.get('q'+ question.qNo).hasError('required')">
                    Answer required</div>
                <div class="invalid-feedback"
                    *ngIf="surveyQuestionForm.get('q'+ question.qNo).touched 
                           && surveyQuestionForm.get('q'+ question.qNo).hasError('max')">
                    max value</div>
                <div class="invalid-feedback"
                    *ngIf="surveyQuestionForm.get('q'+ question.qNo).touched 
                           && surveyQuestionForm.get('q'+ question.qNo).hasError('min')">
                    min value</div>
                <div class="invalid-feedback"
                    *ngIf="surveyQuestionForm.get('q'+ question.qNo).touched 
                           && surveyQuestionForm.get('q'+ question.qNo).hasError('notAllUnique')">
                    Already inserted value</div>
                <td>
                    <input type="number" style="width:40px;" id="q{{question.qNo}}_{{a}}"
                        [ngClass]="{'is-invalid': surveyQuestionForm.get('q'+ question.qNo).errors 
                                   && surveyQuestionForm.get('q'+ question.qNo).touched}" formControlName="{{anwr}}" class="text-center" />
                </td>
            </tr>

        </table>
    </div>
</div>

Here is stackblitz code https://stackblitz.com/edit/angular-pxdesk

please tell me what is the problem having this.

thanks

1 Answer 1

2

the problem here is you're not differentiating between the group having an error or the control having an error.

you need to make sure you're accessing the error on the control when the validator is o the control, and on the group when it's on the group, so you need to be doing this:

<div class="invalid-feedback"
    *ngIf="surveyQuestionForm.get('q'+ question.qNo).get(anwr).touched && surveyQuestionForm.get('q'+ question.qNo).get(anwr).hasError('required')">
    Answer required</div>
<div class="invalid-feedback"
    *ngIf="surveyQuestionForm.get('q'+ question.qNo).get(anwr).touched && surveyQuestionForm.get('q'+ question.qNo).get(anwr).hasError('max')">
    max value</div>
<div class="invalid-feedback"
    *ngIf="surveyQuestionForm.get('q'+ question.qNo).get(anwr).touched && surveyQuestionForm.get('q'+ question.qNo).get(anwr).hasError('min')">
    min value</div>

for the control level errors. If you don't make sure to be checking if the control has been touched as well, then the errors will appear at the wrong time.

for the group level error, you probably want to move it outside of the individual controls, and display it with the group, since it is a group level error. In your current scheme, if you had a duplicate value, the error would appear next to every touched control. so do this instead...

<div class="invalid-feedback"
        *ngIf="surveyQuestionForm.get('q'+ question.qNo).touched && surveyQuestionForm.get('q'+ question.qNo).hasError('notAllUnique')">
        Already inserted value</div>

outside of your ngFor over the answers. notice here, we're accessing the group since this is a group level error.

side note: you probably want your max validator to be 4 and not 3, since you want 4 different numbers.

here is the fixed blitz: https://stackblitz.com/edit/angular-hbtvnc?file=src/app/app.component.html

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

5 Comments

thanks alot bryan60.Now it's working.You did a huge help for me.Highly appreciate your effort.
hi bryan60, I have an another question related to data load to a grid.I opened a question.Please if you have a time,look at this stackoverflow.com/questions/57234640/…
bryan60,please help me if you have a time,I opened 3 questions,but didn't get a answer stackoverflow.com/questions/57239513/…
Sorry I’m not really familiar with either of those grid systems / what they expect / how they work
it's ok bryan.Then do you have an idea about this stackoverflow.com/questions/57239513/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.