Reputation: 8833
I'm trying to use *ngFor
for a set of identical inputs save for the property the input should bind to.
<mat-form-field *ngFor="let prop of [ID, Name, Nickname]">
<input matInput type="text" placeholder="prop.key" #propInput [(ngModel)]="prop">
<button mat-icon-button matSuffix mat-icon-button *ngIf="propInput.value" (click)="prop='';">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<!-- bind test -->
<input matInput type="text" placeholder="Name Test" #propInput [(ngModel)]="Name">
prop.key
does not work, but that is a separate question.
Here is the tethered component:
import { Component } from '@angular/core';
import { EntitySrcService } from '../entity-src.service';
@Component({
selector: 'app-entity-table',
templateUrl: './entity-table.component.html',
styleUrls: ['./entity-table.component.less']
})
export class EntityTableComponent {
constructor(
private entitySrc: EntitySrcService
) {}
public get ID(): string {
return this.entitySrc.id;
}
public set ID(value: String) {
this.entitySrc.id = value;
}
public get Name(): string {
return this.entitySrc.name;
}
public set Name(value: String) {
this.entitySrc.name = value;
}
public get Nickname(): string {
return this.entitySrc.altName;
}
public set Nickname(value: String) {
this.entitySrc.altName = value;
}
}
For the most part this seems to work as expected, but it seems the [(ngModel)]
bind is only reading the property and not writing to it. So for example, if I update the bind test input, the Name field in the ngFor
loop updates to match, but updating the one in the ngFor
loop does not update the one in the test.
I'm using get/set
properties in the component to proxy to the actually storage location, but my understanding is that a get/set
property should act the same as a normal property (and using a normal property has the same one way bind behavior).
So how do I properly iterate over a set of properties that I want to bind to?
Upvotes: 1
Views: 2162
Reputation: 73721
The array [ID, Name, Nickname]
contains the values of the three properties, not their references. The two-way binding will modify the array items instead of the original properties (for that to work, you must refer to the items by their index and track the array by index, as shown in this answer).
To achieve two-way binding of the component properties, you could use an array of property names, and refer to each property with this[prop]
:
<mat-form-field *ngFor="let prop of ['ID', 'Name', 'Nickname']">
<input [(ngModel)]="this[prop]" ... >
...
</mat-form-field>
See this stackblitz for a demo.
Upvotes: 2
Reputation: 2926
It looks that [ID, Name, Nickname]
are value types. In this case *ngFor
just uses their values without binding to the original variables.
If you still need binding, you should consider transforming them to reference types.
For example you could put them into the object, like person or options and iterate object properties using KeyValuePipe
:
How to iterate object keys using *ngFor
options: {[key: number]: string} = {ID: '1', Name: 'bar', Nickname: 'foo'};
<div *ngFor="let item of options | keyvalue">
Upvotes: 2
Reputation: 598
In Angular 6.1 the KeyValuePipe was introduced which allows you to iterate object properties:
<div *ngFor="let item of object | keyvalue">
{{item.key}}:{{item.value}}
</div>
Docs: https://angular.io/api/common/KeyValuePipe
Upvotes: 0