angularrxjsobservable

How to remove item from observable list?


I have a simple todo list that when clicking on "complete", it should remove that item from the list, but nothing seems to be happenning when clicking on it.

Stackblitz: Link

HTML:

<div *ngIf="list$; else noList">
  <div *ngFor="let data of list$ | async" class="items">
    <div>{{ data.id }} -</div>
    <div>{{ data.description }}</div>
    <button (click)="complete(data)">Complete</button>
  </div>
</div>
<button (click)="add()">Add</button>

<ng-template #noList>
  <h1>Loading...</h1>
</ng-template>

service:

complete(data: any) {
    console.log(data.id);

    let result = this.data$
      .pipe(
        filter((x: any) => x.id !== data.id),
        tap((x: any) => console.log(x))
      )
      .subscribe((val: any) => {
        this.resultObs = of(val);
        console.log(val);
        console.log(this.resultObs);
      });

    return this.resultObs;
  }

Solution

  • The filter pipe operator does not itself filter arrays. It filters data going through the pipe. If you have this:

    arr$: Observable<any[]> = of([1, 2]);
    
    arr$.pipe(
        filter((x) => . . .)
    )
    

    x in the filter function will be the entire [1, 2] array, not each element of the array. filter here filters the entirety of data coming through the pipe. You could use it, for example, to prevent the subscribe callback from running unless the user had more than 4 todos:

    arr$: Observable<any[]> = of([1, 2]);
    
    arr$.pipe(
        filter((todos: any[]) => todos.length > 4)
    ).subscribe(() => {
        console.log("Will not run")
    });
    
    arr$.pipe(
        filter((todos: any[]) => todos.length < 4)
    ).subscribe(() => {
        console.log("Will run, since the length of the array is less than 4")
    });
    

    If you want to transform the object going through the pipe, you'd use map:

    let result = this.data$
      .pipe(
        map((xs: any[]) => xs.filter((x) => x.id !== data.id)),
        tap((xs: any[]) => console.log(x))
      )
      .subscribe((val: any) => {
        this.resultObs = of(val);
        console.log(val);
        console.log(this.resultObs);
      });
    

    This transforms the array held by data using map, by calling the filter method on the array to do the filtering.