5

I have a list of input fields that are generated with a model. I am trying to add validation to them. The requirement is they should not be empty or less than 2 characters. problem is in the documentation only shows validation with non-dynamically generated variable Name. My fields are all generated dynamically. So there is no tempVariableName I can hardcode (otherwise they conflict), so I created temp variable from the name of the property I binded the field to. So I came up with something like this :

    <div *ngFor="let field of connector.configFields">
    <label>{{field.name}}</label>
    <input [(ngModel)]="field.value" [type]="field.name === 'Password' ? 'password' : 'text'"
           placeholder="{{field.name}} (required)"
           ngControl="[fieldName+field.name]"
           required minlength="2"
           #fieldName+[field.name]="ngModel" />
    <div *ngIf="(fieldName+[field.name]).errors && ((fieldName+[field.name]).dirty || (fieldName+[field.name]).touched)">
        <span *ngIf="(fieldName+[field.name]).errors.required">Enter Name</span>
        <span *ngIf="(fieldName+[field.name]).errors.minlength">Name minimum at 2 characters</span>
    </div>
</div>

and the configFields in typescript look like this :

export class FieldModel {
public name: string;
public type: string;
public value: any;

}

But this simply would not work. I am new to angular 2 so I am not exactly sure what I did wrong.

1

3 Answers 3

13

You can use the unique index for each field in the array. Use this together with the name attribute (and ngModel) which will evaluate each form controls separately. So each input field gets the unique name, eg:

name="f{{i}}"

where we get {{i}} from the iteration:

<div *ngFor="let field of connector.configFields; let i = index">

So finally, your template could look like this:

<form #myForm="ngForm">
  <div *ngFor="let field of connector.configFields; let i = index">
    <input name="f{{i}}" [(ngModel)]="field.value" [type]="field.name === 'Password' ? 'password' : 'text'" required #f="ngModel" minlength="2"/>
    <div *ngIf="f.errors && (f.dirty || f.touched)">
      <div *ngIf="f.errors.required"> This field is required </div>
      <div *ngIf="f.errors.minlength"> Min 2 chars </div>
    </div>
  </div>
</form>

Here's a live

Demo

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

5 Comments

This is interesting. This means that angular can bind value to frontend temp variables as well as the backend code.
Not really sure what you mean? With backend code, do you refer to a model/values received from backend that can be set e.g as default values, or what do you mean? :)
BTW, I changed one-way binding to two-way binding of your fields, since I saw you have used it in your question, so in case you need/want it...
Glad to hear! :) Have a great day/evening/morning depending on your timezone :P and happy coding!
nice simple explanation. Got a proper answer from here.. Thanks a lot
0

Prepare data in model and return to angular. Angular and hard logic in the template = bad friends.

Comments

0

But if you have a select option and if has *ngFor for option then error message loses its mapping, due second *ngFor loop

better to define custom class for error message and use css display: none or **block*

.custom-valid-box{
  display: none;
 }

.form-control-danger + .custom-valid-box{
   display: block;
 }

Comments

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.