How can I update only part of a list?

Context:

Problem: Every single item in my list is destroyed and recreated even though the input is the same

The reason why the list is replaced by another list is because an observable is behind it (angularfire2). How can I avoid the entire list reloading? Is there a way of maybe creating separate observable for each item in that list and instead let those listen for changes?

Uncertain whether this should be tagged with angularfire2 since I can create the same problem in angular2. Leaving some angularfire2 in comments

Plnkr: http://plnkr.co/edit/qSX9nRGGVNUkD5qIHOMl?p=preview

import { Component, Input } from '@angular/core';
//import { AngularFire, FirebaseListObservable } from 'angularfire2';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Component({
  selector: 'my-app',
  template: '<p *ngFor="let item of items | async"><test [options]="item"></test></p>'
})
export class AppComponent {
  public items = new BehaviorSubject([{bah: 1},{bah: 2},{bah: 3}]);
  //public items: FirebaseListObservable<any[]>;

  constructor() {//af: AngularFire) {

    setTimeout(() => {
      this.items.next([{bah: 1},{bah: 2},{bah: 3},{bah: 4}]);
    },3000);

    /*this.items = af.database.list('/items');
    this.items.push(1);
    setTimeout(() => {
      this.items.push(2);
    },3000);*/
  }
}

@Component({
  selector: 'test',
  template: '{{JSON.stringify(options)}}'
})
export class TestComponent {
  public JSON = JSON;
  @Input() options;

  ngOnChanges(changes) { console.log('ngOnChanges'); }
  ngOnDestroy() { console.log('ngOnDestroy'); }
  ngOnInit() { console.log('ngOnInit'); }
}

Upvotes: 1

Views: 715

Answers (1)

Meir
Meir

Reputation: 14395

You can use trackBy:

  template: '<p *ngFor="let item of items | async; trackBy: itemToIndex" class="my-animation"><test [options]="item"></test></p>'

Track by should be a function, so your plnkr example should be updated to:

  itemToIndex(item: any){
    return item.index;
  }

Upvotes: 2

Related Questions