Search code examples
javascriptangularjsangularngmodel

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()
}

Solution

  • 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="order" 
          title="order" 
          [(ngModel)]="itemsInNewOrder[i].value"/>
      </div>