我正在尝试在Angular 2中创建一个自定义Pipe,它将对一组对象进行排序。我从this post获得了一些帮助。但是,我似乎无法使其发挥作用。
我的烟斗看起来像这样:
@Pipe({
name: "orderByAsync",
pure: false
})
export class AsyncArrayOrderByPipe {
private _promise : Promise<Array<Object>>;
private _output: Array<Object>;
transform(promise: Promise<Array<Object>>, args: any): Array<Object>{
var _property : string = "";
var _descending : boolean = false;
this._property = args[0]["property"] || "";
this._descending = args[0]["descending"] || false;
if(!this._promise) {
this._promise = promise.then((result) => {
result.sort((a: any, b: any) => {
if (a[this._property] < b[this._property]) return (this._descending ? 1: -1);
else if (a[this._property] > b[this._property]) return (this._descending ? -1: 1);
else return 0;
});
this._output = result;
});
}
return this._output;
}
}
管道的使用如下所示:
<div *ngFor="#c of countries | orderByAsync">{{c.name}}</div>
就像从未通知视图已经解决了承诺并且已经返回数据。
我错过了什么?
答案 0 :(得分:13)
内置async
管道会在promise解析时注入ChangeDetectorRef
并在其上调用markForCheck()
。要在一个管道中完成所有操作,您应该遵循该示例。您可以查看here的Typescript源。
async
管道链接它。为此,您可以编写管道以处理裸Array
,而不是承诺,并像这样使用它:
<div *ngFor="#c of countries | async | orderBy">{{c.name}}</div>
答案 1 :(得分:1)
只需将一个BehaviorSubject从管道中返回,然后可以使用角度异步管道绑定。
小例子(把它放在管道的变换方法中)应该给你的价值&#39; 3秒后:
const sub = new BehaviorSubject(null);
setTimeout(() => { sub.next('value'); }, 3000);
return sub;
完整示例:
import { IOption } from 'somewhere';
import { FormsReflector } from './../forms.reflector';
import { BehaviorSubject } from 'rxjs';
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'getOptions' })
export class GetOptionsPipe implements PipeTransform {
public transform(value, ...args: any[]) {
const _subject = new BehaviorSubject('-');
if (args.length !== 2) {
throw `getOptions pipe needs 2 arguments, use it like this: {{ 2 | getOptions:contract:'contractType' | async }}`;
}
const model = args[0];
if (typeof model !== 'object') {
throw `First argument on getOptions pipe needs to be the model, use it like this: {{ 2 | getOptions:contract:'contractType' | async }}`;
}
const propertyName = args[1];
if (typeof propertyName !== 'string') {
throw `Second argument on getOptions pipe needs to be the property to look for, ` +
`use it like this: {{ 2 | getOptions:contract:'contractType' | async }}`;
}
const reflector = new FormsReflector(model);
reflector.resolveOption(propertyName, value)
.then((options: IOption) => {
_subject.next(options.label);
})
.catch((err) => {
throw 'getOptions pipe fail: ' + err;
});
return _subject;
}
}