Reputation: 3617
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>
Upvotes: 76
Views: 317605
Reputation: 1
Find that item index and then update it.
public editData(key: any, Value: any) {
const index = this.EmpData.findIndex((item) => item.id === key.id);
console.log(index);
if (index !== -1) {
Value.value.id = key.id;
this.EmpData[index] = Value.value;
const jsonData = JSON.stringify(this.EmpData);
localStorage.setItem('EmpData', jsonData);
}
}
Upvotes: 0
Reputation: 13297
Update:
showUpdatedItem(newItem){
let indexToUpdate = this.itemArray.items.findIndex(item => item.id === newItem.id);
this.itemArray.items[indexToUpdate] = newItem;
// some angular libraries require breaking the array reference
// to pick up the update in the array and trigger change detection.
// In that case, you can do following
this.itemArray.items = Object.assign([], this.itemArray.items);
}
Original Answer:
I have created this Plunker based on your example that updates the object equal to newItem.id
Here's the snippet of my functions:
showUpdatedItem(newItem){
let updateItem = this.itemArray.items.find(this.findIndexToUpdate, newItem.id);
let index = this.itemArray.items.indexOf(updateItem);
this.itemArray.items[index] = newItem;
}
findIndexToUpdate(newItem) {
return newItem.id === this;
}
Upvotes: 116
Reputation: 31
You can update one item like.
let item = list.find(item => item.id === id);
if( item ) {
item.name = 'other name';
}
Upvotes: 3
Reputation: 81
Try Array.ForEach()
method.
itemArray.ForEach(item =>{
if(item.id == newitem.id){
item.name = newitem.name
}
});
Upvotes: 8
Reputation: 1980
Another approach could be:
let myList = [{id:'aaa1', name: 'aaa'}, {id:'bbb2', name: 'bbb'}, {id:'ccc3', name: 'ccc'}];
let itemUpdated = {id: 'aaa1', name: 'Another approach'};
myList.find(item => item.id == itemUpdated.id).name = itemUpdated.name;
Upvotes: 35
Reputation: 322
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;
}
Upvotes: 2
Reputation: 2211
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>
Upvotes: 0
Reputation: 1383
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;
}
});
Upvotes: 9
Reputation: 13
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;
}
}
}
Upvotes: 0
Reputation: 1088
I would rather create a map
export class item{
name: string;
id: string
}
let caches = new Map<string, item>();
and then you can simply
this.caches[newitem.id] = newitem;
even
this.caches.set(newitem.id, newitem);
array is so 1999. :)
Upvotes: 3
Reputation: 904
Updating directly the item passed as argument should do the job, but I am maybe missing something here ?
updateItem(item){
this.itemService.getUpdate(item.id)
.subscribe(updatedItem => {
item = updatedItem;
});
}
EDIT : If you really have no choice but to loop through your entire array to update your item, use findIndex :
let itemIndex = this.items.findIndex(item => item.id == retrievedItem.id);
this.items[itemIndex] = retrievedItem;
Upvotes: 44