Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2: Two-way binding on Map objects

Tags:

angular

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>
like image 821
arkhamvm Avatar asked May 02 '17 09:05

arkhamvm


People also ask

Does angular2 support 2 way binding?

Angular v2+ supports two-way data binding using ngModel directive and also by having getter and setter methods.

What is 2way binding?

Two-way binding gives components in your application a way to share data. Use two-way binding to listen for events and update values simultaneously between parent and child components.

Is @input two-way data binding?

The answer is "no". In your example, the value that you pass to the @Input property is a reference to an object. If you had two-way binding, you could assign a new object to that property in the child component: and the corresponding property in the parent component would be updated accordingly.

Which Angular module helps you achieve two-way data binding?

Two-way data binding can be achieved using a ngModel directive in Angular. The below syntax shows the data binding using (ngModel), which is basically the combination of both the square brackets of property binding and parentheses of the event binding.


1 Answers

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.

like image 116
shohrukh Avatar answered Oct 16 '22 14:10

shohrukh