2
votes

I'm a newbie with Angular2 (beta1) and I'd like to implement a sort of simple editable grid, built of 2 components. Here I use two fake-data components to keep things simple. They are (see this Plunker: http://plnkr.co/edit/5cZfLTIlhLc82wWV4PQI):

  • the parent component, named contact. Say it represents a contact with a name.
  • the child component, named entry. Say it represents an entry for a contact, where each contact can include 0 or more entries. Each entry has an address and a zip code.

I'd like to create a form where the user can edit the contact's properties, and also its children entries: he could add a new entry, delete an existing entry, or edit an existing entry.

To this end, the views for both these components provide a form-based template. I can think of this data flow:

  1. contact: the user edits the form and then clicks a submit button to save the whole thing. Thus, I can just have some code handling the submit button and emitting an event as the component output. The contact has an entries array property: I can thus use an ngFor directive in its template to render an entry component for each of them.

  2. entry: the entry has properties addressCtl and zipCtl which represent the control directives included in the ControlGroup representing the whole form. Also, I need a couple of properties to be bound as the input of the component (address and zip), so that in the parent template I can do something like:

    <tr *ngFor="#e of entries">
      <td><my-entry [address]="e.address" [zip]="e.zip"></my-entry></td>
    </tr>
    

Now, it's not clear to me how to shape the relation between the "model" properties representing the control's input, and the "form" directives properties. I should be able to get the address and zip values from the parent component through the [...] binding, and pass the updated values up through an event fired by the child component (e.g. blur?). Does this make sense in the NG2 world? Anyway, I'm missing a piece here: how can I connect the form controls values to the model properties values? Could anyone make this clearer or point to some good docs?

2
why didn't you pass the object e, instead of passing string? i.e <my-entry [entry] = "e"></my-entry>. then in your my-entry component, use ng-model for each input. so you automatically gets 2 way bindings.sdfacre
Thank you, I had not thought about this strategy. I have made a new Plunker for the interested readers at embed.plnkr.co/2y2wew60EJLyu45XxlLg. Please post your comment as a reply so I can mark it as the answer.Naftis
Thanks @Naftis, I have done that. you may edit the answer with your plunker link if you want.sdfacre

2 Answers

1
votes

Just moved the comment to answer...

You can pass the object e, instead of passing string. i.e

<my-entry [entry] = "e"></my-entry>

then in your my-entry component, use ng-model for each input. so you automatically gets 2 way bindings.

2
votes

In fact, using the [...] binding only corresponds to a one-way binding. When the parent property is updated in the parent component, the value is also updated in the child component.

But if you want to update parent attributes from the child, you need to leverage events and @Ouput attribute.

Here is a sample with a labels component:

export class LabelsComponent implements OnInit {
  @Input()
  labels:string[];

  @Output()
  labelsChange: EventEmitter;

  (...)

  removeLabel(label:string) {
    var index = this.labels.indexOf(label, 0);
    if (index != undefined) {
      this.labels.splice(index, 1);
      this.labelsChange.emit(this.labels);
    }
  }

  addLabel(label:string) {
    this.labels.push(this.labelToAdd);
    this.labelsChange.emit(this.labels);
    this.labelToAdd = '';
    this.addAreaDisplayed = false;
  }
}

This way you can leverage two way binding on this component:

<labels [(labels)]="company.labels"></labels>

Hope it answers your question, Thierry