Set ngModel binding property within ngFor with different name for each property

2.4k Views Asked by At

I have an Angular 7 app in which I'd like to have a long list of HTML input components, each sharing similar styles but two-way bind to a different field of a single object in the Typescript file. I thought that this should be achievable with a configuration array and ngFor, similar to this:

app.component.html:

<div *ngFor="let inputConfig of inputConfigs;">
    <input name="{{inputConfig.id}}" type="number" placeholder="{{inputConfig.description}}"
        [(ngModel)]="inputConfig.bindingField">
</div>

app.component.ts:

export class AppComponent {

  public objectToBind = {prop1: 5, prop2: 10, prop3: 30};
  public inputConfigs = [
      { id: "prop1", description: "Property 1", bindingField: this.objectToBind.prop1},
      { id: "prop2", description: "Property 2", bindingField: this.objectToBind.prop2},
      { id: "prop3", description: "Property 3", bindingField: this.objectToBind.prop3}
      // additional fields to follow
  ];
}

The problem with this seems to be that Typescript (or rather, JS) did a copy by value in bindingField: this.objectToBind.prop1, when initiating inputConfigs. The result is that the input component is not actually bound to objectToBind.prop1, but rather to a literal copy of it that nothing references.

Is there a way around this issue where I want to bind to different properties with ngModel under a ngFor? Or do I have no choice but to abandon ngFor and write everything statically in the template? Any help would be greatly appreciated!

Btw, there have been some answers that point to using an index in the ngModel expression, e.g. adding let index = index; in ngFor and using [(ngModel)]="inputConfigs[index].bindingField". That doesn't seem to help though.

2

There are 2 best solutions below

0
On BEST ANSWER

It is bound to inputConfig.bindingField, not objectToBind.prop1.

you need to bind objectToBind[inputConfig.id] to ngModel.

app.component.html:

<div *ngFor="let inputConfig of inputConfigs;">
    <input name="{{inputConfig.id}}" type="number" placeholder="{{inputConfig.description}}"
        [(ngModel)]="objectToBind[inputConfig.id]">
</div>
1
On

Simply you can do it this way as long inputConfigs have objects

  public inputConfigs = [
      { id: "prop1", description: "Property 1", value: 5},
      { id: "prop2", description: "Property 2", value: 10},
      { id: "prop3", description: "Property 3", value: 20}
      // additional fields to follow
  ];

template

<div *ngFor="let inputConfig of inputConfigs;">
    <input name="{{inputConfig.id}}" type="number"[(ngModel)]="inputConfig.value">
</div>

and the value will bound to inputConfig.value for each object