3

I am creating form fields dynamically with ngFor and each field is having unique name attr. I am struggling in their validation. My sample code:

<div *ngFor="let dimension of lstShippingDimensions; let i = index" class="dimension-item">
        <input type="text" name="units-{{i}}" [(ngModel)]="dimension.units" 
        class="first-f" placeholder="# of units" required>
        <input type="text" name="width-{{i}}" [(ngModel)]="dimension.width" 
        class="second-f" placeholder="W" required>
        <input type="text" name="height-{{i}}" [(ngModel)]="dimension.height" 
        class="third-f" placeholder="H" required>
        <input type="text" name="length-{{i}}" [(ngModel)]="dimension.length" 
        class="forth-f" placeholder="L" required>
        <select class="five-f" name="unitType-{{i}}" [(ngModel)]="dimension.unitType" 
        required>
            <option>inches</option>
            <option>feet</option>
        </select>
        <div *ngIf="!units-{{i}}.valid && units-{{i}}.touched" class="text-danger text-left">
            <small *ngIf="units-{{i}}.errors.required">Field is required.</small>
        </div>
    </div>

2 Answers 2

11

somehow resolved this with just adding #units="ngModel". I guess Angular is handling the referencing in ngFor itself. This works perfectly fine:

<div *ngFor="let dimension of lstShippingDimensions; let i = index" class="dimension-item">
    <input type="text" name="units-{{i}}" #units="ngModel" [(ngModel)]="dimension.units" class="first-f" placeholder="# of units" required>
    <input type="text" name="width-{{i}}" [(ngModel)]="dimension.width" class="second-f" placeholder="W" required>
    <input type="text" name="height-{{i}}" [(ngModel)]="dimension.height" class="third-f" placeholder="H" required>
    <input type="text" name="length-{{i}}" [(ngModel)]="dimension.length" class="forth-f" placeholder="L" required>
    <select class="five-f" name="unitType-{{i}}" [(ngModel)]="dimension.unitType" required>
        <option>inches</option>
        <option>feet</option>
    </select>
    <div *ngIf="!units.valid && units.touched" class="text-danger text-left">
        <small># of units is required.</small>
    </div>
</div>
Sign up to request clarification or add additional context in comments.

Comments

1

Your example is a use case example of reactive form handling. Please consider using form array and form group:

<form formArrayName="formArray">
<div *ngFor="let dimension of lstShippingDimensions; let i = index" class="dimension-item" [formGroupName]="i">

        <input type="text" name="units-{{i}}" [formControlName]="'units'"
        class="first-f" placeholder="# of units" required>
        <input type="text" name="width-{{i}}" [formControlName]="'width'" 
        class="second-f" placeholder="W" required>
        <input type="text" name="height-{{i}}" [formControlName]="'height'" 
        class="third-f" placeholder="H" required>
        <input type="text" name="length-{{i}}" [formControlName]="'length'" 
        class="forth-f" placeholder="L" required>
        <select class="five-f" name="unitType-{{i}}" [formControlName]="'unitType'" 
        required>
            <option>inches</option>
            <option>feet</option>
        </select>
        <div class="text-danger text-left">
            <small *ngIf="formArrayName[i].errors.required">Field is required</small>
        </div>
    </div>
</form>

Your initial solution did not work, because !units-{{i}}.valid && units-{{i}}.touched" are not exported to template as you expected. It might work if you would declare it as template variable:

    <input type="text" name="height-{{i}}" [(ngModel)]="dimension.height" 
    class="third-f" placeholder="H" required #templateVar="ngForm">
   <div *ngIf="templateVar.valid && templateVar.touched" class="text-danger text-left">
        <small *ngIf="templateVar.errors.required">Field is required.</small>
    </div>

But template variable names can not be created dynamically, i.e. #DynamicVar-{{i}} is not allowed.

1 Comment

Thanks for the reply. The thing is I am restricted to using template driven form as this is just a small part of my form and other fields of my form are dependent on each other. Is there any work around to achieve this?

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.