How to use custom pipe on async pipe?

15,932

Solution 1

I had the same issue as well the way I fixed it, was like this:

<li class="list-group-item" *ngFor='let alert of _alerts$ | ipwrAlertFilter:seeAll | async'>

look how I had my custom filter before the async pipe, this way my custom pipe gets an observable and then in my pipe I have this:

return value.map(data => data.filter(x => x.originalHasBeenSeen === false));

this way my custom pipe still returns something that I can still apply async pipe on. and so with each new item in stream I still get a hit on my custom pipe and my view gets updated. hope this helps.

Solution 2

The best way to go about it is to still stick with your async and after the async call your custom pipes , like the one in the question, just that your pipe code will now change to not act on the to be loaded array since the record is still loading, so we tell our custom pipe not to do anything again or return empty array. e.g

transform(items: any[], field: string, format?: string) { 
    if (items == null) //since the async is still working
      return [];
//do our normal pipe logic or function
    return items.sort((a: any, b: any) => {
      let value1 = a[field];
      let value2 = b[field];

      if (value1 > value2) {
        return 1;
      } else if (value1 < value2) {
        return -1;
      } else {
        return 0;
      }
    });

then your template still retains

*ngFor = 'let product of $productList | async | sortByName:"A"'

Solution 3

In case this isn't clear for everyone, it's as easy as...

<div *ngFor="let product of (products$ | async | searchFilter: (query$ | async) )">

Notice the brackets (query$ | async) already in an async pipe operation.

Share:
15,932

Related videos on Youtube

Sagar Ganesh
Author by

Sagar Ganesh

I love &lt;3 new technologies. :)

Updated on June 04, 2022

Comments

  • Sagar Ganesh
    Sagar Ganesh almost 2 years

    I'm trying to create custom pipe on asynchronous pipe, I tried many solutions, but still not working. Here is the snippet of code.

    product.sort.ts - custom pipe

    import { PipeTransform, Pipe } from '@angular/core';
    import { Observable } from 'rxjs/Observable';
    
    @Pipe({
        name: 'sortByName'
    })
    export class ProductPipe implements PipeTransform{
        /*transform(values: Array<any>, term:string){
            return values.filter(obj => obj.pname.startsWith(term))
        }*/
    
        //CODE NOT WORKING >>>>>
        transform($value: Observable<Array<any>>, term:string){
            if($value){
                $value.subscribe(
                    (obj) => {
                        return obj.filter(obj => obj.pname.startsWith(term))
                    }
                )
            }
        }
    }
    

    products.component.ts - main component

    import { Component, OnInit } from '@angular/core';
    import { Store } from '@ngrx/store';
    import { Observable } from 'rxjs/Observable';
    import { AppService } from '../app.service/app.service';
    import { ProductPipe } from '../products.sort/products.sort';
    
    @Component({
        selector: 'products-pg',
        template: `
            Products List:
            <ul>
                <li *ngFor = 'let product of $productList | async | sortByName:"A"'>{{product.pname}}</li>
            </ul>
        `
    })
    export class ProductsComponent implements OnInit{
        private $productList:Observable<Array<any>>;
    
        constructor(private _service: AppService, private _store: Store<Array<any>>){}
    
        ngOnInit(){
            this._service.setProductList();
            this.$productList = this._store.select('products');
        }
    }
    

    Here, I'm using store for state management, I'm trying to sort by name, so passing "A" as first letter. Since $productList is observable, how to write pipe which handles asynchronous behavior like this, plase help me to solve this.

    • jonrsharpe
      jonrsharpe over 7 years
      Your pipe is not getting an observable. That's the whole point of putting | async before calling your own pipe. It resolves the observable and returns the result, an array. Why have you commented out the code that takes an array? What was the initial problem that led to your trying to rewrite the pipe?
  • Sagar Ganesh
    Sagar Ganesh about 7 years
    thanks @Aran Dehkharghani, this is another way to do it.
  • Ultranuke
    Ultranuke almost 5 years
    Thanks, also for the last line in my case I had to use the map operator return value.pipe(map(el => el.value));