Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

two-way binding arrays in angular 2

I'm aware with basic 2-way binding in angular 2 as shown in the docs.

I have an array of persons, which I'm using to build an html list:

Now, when I click on a person's row, I can edit it using 2-way binding:

 <form>
    <label>Name: </label>
    <input [(ngModel)]="selectedPerson.name" name="name"/>

    <label>Description: </label>
    <input [(ngModel)]="selectedPerson.job" name="job"/>
</form>

Now, what I want is to 2-way bind the list itself: (The list is in a different view than the row editor)

 <div class='row' *ngFor="let person of model">
    <div class='col'>{{person.name}}</div>
    <div class='col'>{{person.job}}</div>
 </div>

Currently, I'm using *ngFor to list out all persons. If my model is an array of two persons, I get two rows. There are cases when the model might change to have 3 or 4 persons. Is there any way I can make angular detect this and add rows accordingly? [(ngModel)] doesn't seem to be applicable here.

Basically, I want my list view to update without having to refresh the page. How to I make the model used in ngFor listen to changes?

like image 781
Snowman Avatar asked Oct 03 '16 13:10

Snowman


People also ask

Does Angular have 2 way binding?

The two-way data binding in Angular is used to display information to the end user and allows the end user to make changes to the underlying data using the UI. This makes a two-way connection between the view (the template) and the component class.

How is angular 2 way binding implemented?

Angular's two-way binding syntax is a combination of square brackets and parentheses, [()] . The [()] syntax combines the brackets of property binding, [] , with the parentheses of event binding, () , as follows.

What is one-way binding and two-way binding in Angular?

Difference between One-way & Two-way Binding This means that the flow of code is from ts file to Html file as well as from Html file to ts file. In order to achieve one-way binding, we used the property binding concept in Angular. In order to achieve a two-way binding, we will use ngModel or banana in a box syntax.


2 Answers

Thanks to @David Blaney. I am not sure if I can post it. I only wanted to extend your example to edit grid / edit table with two-way binding array directly on every row in the table - angular is taking care of updating the Array as user is writing in the "input element directly in the table". User can quickly edit the elements without first selecting the row in the table. In the original example of @David Blaney in the plunker I just replaced the whole table element in app/editor.component.ts with this:

<form id="bigForm">
  <table>
    <tr class='row'>
        <th class='col'>Name</th>
        <th class='col'>Job</th>
    </tr>
    <tr class='row' *ngFor="let person of model; let i = index" (click)="selectPerson(person)" >
      <td class='col'>
        <input [id]="'person.name' + i" [(ngModel)]="person.name" [name]="'person.name' + i"/>
        - {{person.name}}
      </td>
      <td class='col'>{{person.job}}</td>
    </tr>
  </table>
</form>

Then I can post several changed rows to the http server in one request.

like image 177
vlakov Avatar answered Oct 11 '22 01:10

vlakov


Here is a plunker of an example of how you can bind your model variable to another component:

https://plnkr.co/edit/tM20HcUIx13ZUPh0faTB?p=preview

I have created a simple list component from your code above:

import { Component, Input  } from '@angular/core';

import { Person } from './person';

@Component({
  selector: 'my-list',
  template:`
    <h3>The List</h3>
    <tr class='row' *ngFor="let person of model">
      <td class='col'>{{person.name}}</td>
      <td class='col'>{{person.job}}</td>
    </tr>
})

export class List {
  @Input() model:Array<Person>;  
}

The Input decorator lets the component know to expect and input of this type and to use it in the scope of this component.

In the template of the editor component I have used the my-list directive and set the model input of the directive to the model in the editor component.

<my-list [model]="model" ></my-list>

This now lets any changes to the model be reflected int he child list component.

If you were wanting you notify a component that was not a child of the editor component you would need to use the @Output decorator and set up an EventEmitter that a listener can be bound to and then used to updated the list elsewhere.

Take a look at the documentation here:

https://angular.io/docs/ts/latest/cookbook/component-communication.html

like image 3
David Blaney Avatar answered Oct 11 '22 00:10

David Blaney