angulartypescriptangular-formsangular-template-form

Validating array of input fields in Angular 2+


In this plunk I have an Angular form that contains one input field followed by an array of input fields. I need to validate that any of these fields is not empty.

The single field works well, but I'm struggling with validating the array of fields, I'm getting an error Error: Cannot assign to a reference or variable! when the form is displayed. Any ideas how to fix the plunk attempt?

@Component({
  selector: 'my-app',
  template: `
   <form #f="ngForm" name="form" (ngSubmit)="ok(f.form)" novalidate>
       <input name="singleField" id="singleField" [(ngModel)]="field1"  
              #singleField="ngModel" required />
       <div *ngIf="singleField.touched || submitted" class="errorMsg">
            <label *ngIf="singleField.control.hasError('required')">
                Field is required
            </label>
       </div>
       <br/><br/>
       <div *ngFor="let field2 of manyFields; let i = index">
           <input name="field" id="field" [(ngModel)]="field2"  
                  #field="ngModel" required />
           <div *ngIf="field.touched || submitted" class="errorMsg">
                <label *ngIf="field.control.hasError('required')">
                    Field is required
                </label>
           </div>
       </div>
       <br/><br/>
       <button type="submit">Submit</button>
   </form>
  `,
  styles: [`
    .errorMsg {
      color: red;
    }
  `]
})
export class App {

       field1: string = 'delete this';
       manyFields: string[] = ['Field 1', 'Field 2', 'Field 3'];

       ok(form: any){
            if (form.valid)
                 alert("Form is valid");
            else     
                 alert("Form is NOT valid");
       }
}

Solution

  • Error: Cannot assign to a reference or variable error because [(ngModel)]="field2" you can't assaign field2

    this solve the error and make the required validation work

    <input [name]="field2" [id]="field2" ngModel #field="ngModel" required /> 
    

    I have use the value of field from name and id attribute.

    validate dynamic fields

      manyFieldsValidators(form: any) {
        let fields: string[] = [];
    
        if (form && form.value) {
          for (let f of this.manyFields) {
            if (form.value[f] === '') {
              fields.push(f)
            } 
          } 
        }
    
        if (fields.length > 0) {
          return { fields: true, message: `${fields.join(',')} are empty` }
        } else {
          return { fields: false, message: '' }
        }
    
      } 
    

    template

        <div class="errorMsg" *ngIf="manyFieldsValidators(f).fields">
            {{manyFieldsValidators(f).message}}
        </div>
    

    stackblitz demo

    template form is meant for simple form ,validation can be done in more cleaner way by reactive form Form Array you may consider to use reactive form