Implementing an asynchronous sorting channel in Angular 2

I am trying to create a custom tube in Angular 2 that sorts an array of objects. I got a little help from this post . However, I cannot get this work to work.

My pipe looks like this:

@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; } } 

Using the pipe will look like this:

 <div *ngFor="#c of countries | orderByAsync">{{c.name}}</div> 

He, like the submission, is never notified that the promise has been resolved and the data has been returned.

What am I missing?

+5
source share
2 answers

The async built into the tube introduces ChangeDetectorRef and calls markForCheck() on it when the promise is resolved. To do this in one pipe, you must follow this example. You can view the Typescript source for this here .

I would advise, however, to forget about processing async yourself and instead write a clean stateless sorting tube and associate it with the built-in async pipe. To do this, you must write your pipe to handle the bare Array , not the promise, and use it as follows:

 <div *ngFor="#c of countries | async | orderBy">{{c.name}}</div> 
+7
source

Just return the BehaviorSubject from your channel, which can then be connected to the angular asynchronous channel.

A small example (put it in your channel conversion method) that should give you a β€œvalue” after 3 seconds:

 const sub = new BehaviorSubject(null); setTimeout(() => { sub.next('value'); }, 3000); return sub; 

Full example:

 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; } } 
+1
source

Source: https://habr.com/ru/post/1244854/


All Articles