0

I have a list of products. Each product has an id and description.

<div *ngFor="let product of products">
  <input type="text" [ngModel]="product.description" (ngModelChange)="onEdit($event, product.id)">
</div>

editStream: EventEmitter<any> = new EventEmitter();

ngOnInit() {
  this.editStream
    .debounceTime(1000)
    .distinctUntilChanged()
    .mergeMap(x => Observable.of(x))
    .subscribe(x => {
      // based on product id, update its description in the database
    });

}

private onEdit(description: string, id: string) {
  this.editStream.emit({ description, id });
}

It works well when I edit one product's description.

However, if I edit product1's description, then edit product2's description immediately (time interval is less than 1s), only product2's description will be updated.

I guess this is because product2's event overwrites product1's event, and I only subscribe at one place.

How can I solve this? Thanks

Hongbo Miao
  • 45,290
  • 60
  • 174
  • 267

1 Answers1

2

If you want to use distinctUntilChanged() you need a different Observable for each product.

this.products.forEach(p => this.editStreams.push(new EventEmitter())
<div *ngFor="let product of products let i=index">
  <input type="text" [ngModel]="product.description" (ngModelChange)="onEdit($event, i, product.id)">
</div>
private onEdit(description: string, id: string) {
  this.editStreams[i].emit({ description, id });
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Hm, what do you mean "different Observable for each product"? – Hongbo Miao Jun 13 '16 at 05:40
  • Got it, is there a smart way to create certain number (based on product number) of `editStream`? Use an editStream array? – Hongbo Miao Jun 13 '16 at 05:42
  • I updated my answer with a few code snippets. You also would need to subscribe to each item in `editStreams` individually (what you do in `ngOnInit()`). I don't know of a smarter way. That doesn't mean there isn't one ;-) – Günter Zöchbauer Jun 13 '16 at 05:47
  • Looks great. But say I have 500 products. Your way needs create 500. Maybe create editStream **when only need**. Most time only 1 or 2. Because in 1s, you can only edit 2 together. Can you give me some hint how to do this? – Hongbo Miao Jun 13 '16 at 05:52
  • 1
    You might want to setup just one at the time when the input is focused. `(focus)="setupObservable(i)"`, and when one is already set up, unsubscribe it. – Günter Zöchbauer Jun 13 '16 at 05:54