How i can use two-way binding on Map objects?
The following code doesn't work as expected:
Component:
@Component({
moduleId: module.id,
selector: "my-component",
templateUrl: "my-component.html",
styleUrls: ["my-component.scss"],
})
export class MyComponent {
myMap: Map<string, Object> = Map<string, Object>()
.set('first', {text: 'abc'})
.set('second', {text: 'foo'})
;
}
Template:
<div class="items" *ngFor="let item of myMap.values()">
<input type="text" [(ngModel)]="item.text" />
</div>
Actually in this example two-way data binding works as expected. Probably your mistake is in creating Map object:
myMap: Map<string, Object> = Map<string, Object>()
You have to include new keyword before Map (because Map Constructor is not callable):
myMap: Map<string, Object> = new Map<string, Object>()
.set('first', {text: 'abc'})
.set('second', {text: 'foo'})
And now everything works as expected. You can check this stackblitz demo as well.
Notice: According to this Angular issue on GitHub: Maps have no orders in keys and hence they iteration is unpredictable. This was supported in ng1, but we think it was a mistake and will not be supported in NG2.
One of the simplest solutions for this - is to use Array.from() method on myMap.entries():
getEntities() {
// this will return [['first', { text: 'abc' }], ... ]
// and after mapping we get [{ text: 'abc' }, ...]
return Array.from(this.myMap.entries()).map(item => item[1]);
}
And now we can use it in the template:
<div class="items" *ngFor="let item of getEntities()">
<input type="text" [(ngModel)]="item.text" />
</div>
In this example two-way data-binding works as well.