How to use custom pipe on async pipe?

*爱你&永不变心* 提交于 2019-12-10 15:54:36

问题


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.


回答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.




回答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"'



回答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.



来源:https://stackoverflow.com/questions/41548035/how-to-use-custom-pipe-on-async-pipe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!