javascript - trackBy med async-pipen
Jag försöker använda async-pipe med *ngFor för att visa en array av objekt som hämtas asynkront.
<ul>
<li *ngFor="let item of items | async; trackBy: trackPost">
{{item.text}}
</li>
</ul>
ngOnInit() {
// very simple http call; returns an array of [{id: 1, text: "something"}]
this.items = this.itemService.loadItems();
}
trackPost(index, item) { return item.id; }
Detta fungerar bra. Sedan vill jag lägga till ett objekt:
async addItem(text) {
await this.itemService.addItem({text});
// reload items after adding
this.items = this.itemService.loadItems();
}
Detta fungerar också, och det kommer att uppdatera objekten korrekt efter att det har lagts till.
Problemet är att det kommer att ladda om hela arrayen istället för att bara lägga till objekt. Du kan märka detta med animationer (om du animerar objekt in). Jag vet att jag kan hantera prenumerationen själv och arbeta med en array, men jag undrar om det finns ett sätt att göra detta med async-pipen.
Finns det ett sätt för mig att lägga till det nya objektet på det befintliga observerbara? Om inte det är möjligt, finns det ett sätt att få mallen att korrekt följa objekten istället för att se dem som att de läggs till på nytt?
Svar #1
Problemet är att du tilldelar om strömmen via this.items=this.itemService.loadItems();. Så din Observable items skickar inte ut nya värden, vilket Angular skulle spåra med din trackBy-funktion, utan du ändrar referensen för items, vilket får Angular att göra en fullständig omladdning.
Så ändra bara din addItem-funktion i din tjänst för att sända de uppdaterade värdena till din tidigare erhållna Observable via loadItems. Efter det kallar du helt enkelt
addItem(text) {
this.itemService.addItem({text});
}
Exempel på en tjänst:
@Injectable()
export class Service {
private items: Array<string> = [];
private items$ = new Subject<Array<string>>();
loadItems(): Observable<Array<string>> {
return this.items$.asObservable();
}
addItem(text: string) {
this.items = [...this.items, text];
this.items$.next(this.items);
}
}
