skip to Main Content

I have a dynamic reactive angular form which builds forms and populates questions inside it dynamically according to questions types retrieved from the database. the problem is the required validation (native HTML5 validation ngNativeValidate) is not working when I add it inside a *ngFor loop

in my form builder I have this part

<div class="row" *ngSwitchCase="'radiobtn'">
      <legend class="col-form-label col-sm-6 pt-0">{{question.label}}</legend>
      <div class="col-sm-6">
        <div class="form-check" *ngFor="let opt of question.options; let i = index">
          <label class="form-check-label" [attr.for]="question.key+opt.key">
          <input class="form-check-input" type="radio" [name]="question.key" [formControlName]="question.key"
[id]="question.key+opt.key" [value]="opt.key" required />
            {{opt.value}}
          </label>
        </div>
      </div>
    </div>

I have ngNativeValidate in the form tag and I have new FormControl(question.value || '', Validators.required) in the FormGroup builder.

This code is supposed to apply required validation check but it’s not working. when I remove the for loop and make it static the validation works. what is the reason here.

Note: my Angular version is 10

2

Answers


  1. Chosen as BEST ANSWER

    input[radio] needs to have both [name] and [attr.name] to be set.


  2. When working with native validations always prefer Template Driven Forms, because if you go for template driven, the validation you add, will not trigger the native HTML validations.

    HTML:

    <div class="jumbotron text-center">
      <h1 class="display-5">Radio Buttons in Angular</h1>
    </div>
    
    <div class="container">
      <div class="row custom-wrapper">
        <div class="col-md-12">
          <!-- Form starts -->
          <form (ngSubmit)="onSubmit()" #actorForm="ngForm" ngNativeValidate>
            <!-- Gender -->
            <div class="group-gap">
              <h5 class="mb-3">Gender</h5>
              <div class="d-block my-3">
                <div *ngFor="let gender of questions[0].genders; let i = index">
                  <label [for]="gender">
                    <input
                      type="radio"
                      name="gender"
                      [id]="gender"
                      [(ngModel)]="genderVal"
                      [value]="gender"
                      required
                    />
                    {{ gender }}
                  </label>
                </div>
              </div>
            </div>
    
            <!-- Submit Button -->
            <button type="submit" class="btn btn-danger btn-lg btn-block">
              Submit
            </button>
          </form>
          <!-- Form ends -->
        </div>
      </div>
    </div>
    

    TS:

    import { Component, ViewChild } from '@angular/core';
    import { NgForm } from '@angular/forms';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
    })
    export class AppComponent {
      @ViewChild('actorForm') registrationForm: NgForm;
      isSubmitted = false;
      questions: { genders: string[] }[] = [{ genders: ['Male', 'Female'] }];
      genderVal = '';
    
      // Submit Registration Form
      onSubmit() {
        this.isSubmitted = true;
        alert(JSON.stringify(this.registrationForm.valid));
        if (!this.registrationForm.valid) {
          return false;
        } else {
          alert(JSON.stringify(this.registrationForm.value));
        }
      }
    }
    

    Stackblitz Demo

    But here is an example of reactive driven forms, the gotcha you need to know is that.

    When you add a validation, the corresponding directive also needs to be present in HTML, that is why we have required attribute.

    HTML:

    <div class="jumbotron text-center">
      <h1 class="display-5">Radio Buttons in Angular</h1>
    </div>
    
    <div class="container">
      <div class="row custom-wrapper">
        <div class="col-md-12">
          <!-- Form starts -->
          <form
            [formGroup]="registrationForm"
            (ngSubmit)="onSubmit()"
            ngNativeValidate
          >
            <!-- Gender -->
            <div class="group-gap">
              <h5 class="mb-3">Gender</h5>
              <div class="d-block my-3">
                <div *ngFor="let gender of questions[0].genders; let i = index">
                  <label [for]="gender">
                    <input
                      type="radio"
                      name="gender"
                      [id]="gender"
                      formControlName="gender"
                      [value]="gender"
                      required
                    />
                    {{ gender }}
                  </label>
                </div>
              </div>
            </div>
    
            <!-- Submit Button -->
            <button type="submit" class="btn btn-danger btn-lg btn-block">
              Submit
            </button>
          </form>
          <!-- Form ends -->
        </div>
      </div>
    </div>
    

    TS:

    import { Component } from '@angular/core';
    import { FormBuilder, Validators } from '@angular/forms';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
    })
    export class AppComponent {
      isSubmitted = false;
      questions: { genders: string[] }[] = [{ genders: ['Male', 'Female'] }];
    
      constructor(public fb: FormBuilder) {}
    
      /*########### Form ###########*/
      registrationForm = this.fb.group({
        gender: ['', [Validators.required]],
      });
    
      // Submit Registration Form
      onSubmit() {
        this.isSubmitted = true;
        alert(JSON.stringify(this.registrationForm.valid));
        if (!this.registrationForm.valid) {
          return false;
        } else {
          alert(JSON.stringify(this.registrationForm.value));
        }
      }
    }
    

    Stackblitz Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search