40Hz_ringtone 40Hz_ringtone - 1 month ago 17
Javascript Question

How to implement iterated, array-filling Angular 2 inputs?

I want to be able to add/remove items in an order and have them aggregate into an array to be sent to the backend. The data will look like:


  • CustomerName: Billy

  • Orders: [Pizza, Burger, Sushi]



Can't find any SO answers or documentation that gets into iterated input binding. Anyone attempted this? Template code:

<div>
<input
type="text"
name="name"
title="name"
placeholder="Customer Name"
[(ngModel)]="customerName"/>
</div>
<div *ngFor="let item of itemsInNewOrder; let i = index">
<input
type="text"
name="order"
title="order"
[(ngModel)]="itemsInNewOrder[index]"/>
</div>


inside the Add New button's click function:

...firebaseStuff... .push({name: name, order: this.itemsInNewOrder})


unfortunately, this doesn't work. Thanks in advance! :)

Edit 1: There are 2 buttons that trigger (respectively):

incrementItemsInNewOrder() {
this.itemsInNewOrder.push("")
}
decrementItemsInNewOrder() {
this.itemsInNewOrder.pop()
}

Answer

I can see one problem. You should use the variable i that you have declared in template.

<div *ngFor="let item of itemsInNewOrder; let i = index">
  <input 
    type="text" 
    name="order" 
    title="order" 
    [(ngModel)]="itemsInNewOrder[i]"/> <------ HERE
</div>

EDIT

angular seems to be doing change detection when typing into the inputs and renders them again, when that happens you lose the focus.

but if you wrap the values into objects and suddenly it works.

Component:

itemsInNewOrder = [{value: 'Soda'}, {value: 'Burger'}, {value: 'Fries'}];

template:

<div *ngFor="let item of itemsInNewOrder; let i = index">
    <input 
      type="text" 
      name="{{item}}" 
      title="{{item}}"
      [(ngModel)]="itemsInNewOrder[i].value"/>
  </div>
Comments