Angular update object in object array

Viewed 243299

Say i have the following object array, lets name it itemArray;

{
  "totalItems": 2,
  "items": [
    {
      "id": 1,
      "name": "foo"

    },
    {
      "id": 2,
      "name": "bar"
    },
    ]
}

And i have a subscription that returns the updated result of only id 2. How would i update the object array without looping through the entire array?

What i would like is something like the example below;

updateUser(user){
    this.myservice.getUpdate(user.id)
    .subscribe(newitem => {
      this.updateArray(newitem);
    });
}

  updateArray(newitem){
    this.itemArray.items[newitem.id].name = newitem.name
  }

or even better, replacing the entire object;

  updateArray(newitem){
    this.itemArray.items[newitem.id] = newitem
  }

This example however updates the array based on the index of the array. So how do i instead update based on newitem.id?

Template requested in comment:

<tr *ngFor="let u of itemsArray.items; let i = index">
  <td>{{ u.id }}</td>
  <td>{{ u.name }}</td>
  <td>
    <input type="checkbox" checked="u.accepted" [(ngModel)]="itemsArray.items[i].accepted" (ngModelChange)="updateUser(u)">
    <label for="singleCheckbox-{{i}}"></label>
  </td>
</tr>
10 Answers

You can try this also to replace existing object

toDoTaskList = [
                {id:'abcd', name:'test'},
                {id:'abcdc', name:'test'},
                {id:'abcdtr', name:'test'}
              ];

newRecordToUpdate = {id:'abcdc', name:'xyz'};
this.toDoTaskList.map((todo, i) => {
         if (todo.id == newRecordToUpdate .id){
            this.toDoTaskList[i] = updatedVal;
          }
        });

Try Array.ForEach() method.

itemArray.ForEach(item =>{
    if(item.id == newitem.id){
        item.name = newitem.name
    }
});
updateValue(data){    
     // retriving index from array
     let indexValue = this.items.indexOf(data);
    // changing specific element in array
     this.items[indexValue].isShow =  !this.items[indexValue].isShow;
}

You can update one item like.

let item = list.find(item => item.id === id);

if(item)
{
  item.name = 'other name';
} 

You can use for loop to find your element and update it:

updateItem(newItem){
  for (let i = 0; i < this.itemsArray.length; i++) {
      if(this.itemsArray[i].id == newItem.id){
        this.users[i] = newItem;
      }
    }
}

In angular/typescript we can avoid mutation of the objects in the array.

An example using your item arr as a BehaviorSubject:

// you can initialize the items$ with the default array
this.items$ = new BehaviorSubject<any>([user1, user2, ...])

updateUser(user){
   this.myservice.getUpdate(user.id).subscribe(newitem => {

     // remove old item
     const items = this.items$.value.filter((item) => item.id !== newitem.id);

     // add a the newItem and broadcast a new table
     this.items$.next([...items, newItem])
   });
}

And in the template you can subscribe on the items$

<tr *ngFor="let u of items$ | async; let i = index">
   <td>{{ u.id }}</td>
   <td>{{ u.name }}</td>
   <td>
        <input type="checkbox" checked="u.accepted" (click)="updateUser(u)">
        <label for="singleCheckbox-{{i}}"></label>
   </td>
</tr>
Related