2016-03-10 33 views
5

में एक एसिंक्रोनस सॉर्टिंग पाइप को कार्यान्वित करना मैं कोणीय 2 में एक कस्टम पाइप बनाने की कोशिश कर रहा हूं जो वस्तुओं की एक सरणी को सॉर्ट करेगा। मैंने this post से थोड़ी सी सहायता प्राप्त की। हालांकि, मुझे यह काम नहीं मिल रहा है।कोणीय 2

मेरे पाइप इस तरह दिखता है:

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

दृश्य की तरह बात की सूचना नहीं है उस वादे को दूर किया है और डेटा कर दिया गया है यह लौटा हुआ।

मुझे क्या याद आ रही है?

+1

आप कृपया एक त्वरित बना सकता

छोटे उदाहरण है जो आप 3 सेकंड के बाद, 'मान' देना चाहिए (अपने पाइप के अपने को बदलने विधि में रख) बिन तो स्निपेट चारों ओर खेला जा सकता है। –

उत्तर

7

निर्मित async पाइप ChangeDetectorRef इंजेक्ट करता है और वादा हल होने पर markForCheck() पर कॉल करता है। इसे एक पाइप में करने के लिए, आपको उस उदाहरण का पालन करना चाहिए। आप उस here के लिए टाइपस्क्रिप्ट स्रोत देख सकते हैं।

मैं सुझाव दूंगा कि, हालांकि, अपने आप को एसिंक को संभालने के बारे में भूलना और इसके बजाय एक शुद्ध स्टेटलेस सॉर्टिंग पाइप लिखना और इसे async पाइप में बनाया गया है। कि इसके लिए आपको अपना पाइप एक नंगे Array, नहीं एक वादा को संभालने के लिए लिखते थे, और इस तरह इसका इस्तेमाल:

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

मैंने मूल रूप से यह कोशिश की थी; हालांकि, मैं मुद्दों में भाग गया - मुझे लगता है क्योंकि वादे को हल करने से पहले मेरी पाइप को बुलाया जा रहा था, इसलिए मेरा 'array.sort' एक त्रुटि फेंक रहा था। शायद मुझे हल किए गए सरणी में देरी के लिए खाते से शुरू करने के लिए बस एक खाली सरणी को संभालने की आवश्यकता है। मैं उसे एक शॉट दूंगा। – RHarris

+2

@RHarris वादा संकल्प से पहले 'async' पाइप शून्य हो जाता है, इसलिए आपके पाइप को काम करने के लिए त्रुटि के बिना शून्य को संभालने की आवश्यकता होगी। – Douglas

+0

@Douglas 'null'hint के लिए धन्यवाद .. मैंने इस व्यवहार को देखा, लेकिन मैंने सोचा कि मैं एक गलती करता हूं और इस प्रकार' शून्य 'हो जाता है .. लेकिन निश्चित रूप से यह एक अभी तक हल किए गए वादे के लिए वांछित व्यवहार नहीं है;) – wzr1337

1

बस अपने पाइप जो तब कोणीय async पाइप के साथ बाध्य कर सकते हैं के बाहर एक BehaviorSubject लौट आते हैं।

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; 
    } 
} 
+0

हे, मैन, आप संदर्भ को कुछ कोड नहीं डाल सकते हैं।'FormsReflector' के बारे में कोई जानकारी नहीं है, भले ही मैं इसकी कार्यक्षमता का अनुमान लगा सकूं। आपकी प्रेरणा के लिए, +1। –

+0

हाँ, तो महत्वपूर्ण बात यह है कि आपको अपनी पाइप से व्यवहार व्यवहार को वापस करना चाहिए। तो आप किसी भी समय मूल्य भर सकते हैं और यह प्रतिबिंबित हो जाएगा: कॉन्स उप = नया व्यवहार विषय (शून्य); सेटटाइमआउट (() => { sub.next ('value'); }, 3000); वापसी उप; यह आपको जो चाहिए वह छोटा संस्करण है। पाइप्स अपने मूल्यों को एक-दूसरे से धक्का दे रहे हैं। व्यवहार विषय को तब कोणीय के एसिंक पाइप पर पाइप किया जा सकता है। –