2017-02-13 3 views
0

ich eine Liste der Dinge von einer beobachtbaren Feld sortiert werden soll, kann aber nicht den Kopf wickelt um Observablen diese Funktion zu erhalten. Hat jemand eine Idee wie man das erreicht?angular2 rxjs Ordnung (beobachtbar) Liste der Objekte, die von einem beobachtbaren Bereich

Die Ausgangssituation ist in etwa wie folgt.

Thing[] things; 

interface Thing { 
    name: Observable<string> 
} 
<ul> 
    <li *ngFor="const thing for things"> 
    {{thing.name | async}} 
    </li> 
</ul> 

EDIT: Da ich offensichtlich nicht mein Problem richtig beschrieben: Das Feld ich auf die Liste der Dinge sortieren will, ist ein beobachtbares, keine einfacher String. Ich möchte das Feld über Websockets aktualisiert halten, um die Änderungen richtig zu erkennen. Ich muss ein Observable-Feld verwenden, auf dem ich mich anmelden kann.

+0

Was ist die Idee hinter dem Namen als Observable ? Ich denke, dass Sie diese Eigenschaft als eine normale Zeichenfolge verlassen wollen –

+0

Ich möchte das Feld als Observable verwenden, da es Wert zur Laufzeit ändern kann. – sclausen

+0

Phosphoros, Sie sind weder zeichn zum 'name' oder' Thing', aber auf der Liste der Dinge ('beobachtbare ') –

Antwort

5

Dank für die Klärung der Frage, Phosphoros. :)

Hier ist, wie Sie tun können, was Sie gefragt:

// Function to compare two objects by comparing their `unwrappedName` property. 
const compareFn = (a, b) => { 
    if (a.unwrappedName < b.unwrappedName) 
    return -1; 
    if (a.unwrappedName > b.unwrappedName) 
    return 1; 
    return 0; 
}; 

// Array of Thing objects wrapped in an observable. 
// NB. The `thing.name` property is itself an observable. 
const thingsObs = Observable.from([ 
    { id: 1, name: Observable.of('foo') }, 
    { id: 2, name: Observable.of('bar') }, 
    { id: 3, name: Observable.of('jazz') } 
]); 

// Now transform and subscribe to the observable. 
thingsObs 

    // Unwrap `thing.name` for each object and store it under `thing.unwrappedName`. 
    .mergeMap(thing => 
    thing.name.map(unwrappedName => Object.assign(thing, {unwrappedName: unwrappedName})) 
) 

    // Gather all things in a SINGLE array to sort them. 
    .toArray() 

    // Sort the array of things by `unwrappedName`. 
    .map(things => things.sort(compareFn)) 

    .subscribe(); 

Logging emittierten Werte an die Konsole wird durch ihre unwrappedName Eigenschaft ein Array von Thing Objekte geordnet zeigen:

[ 
    { id: 2, name: ScalarObservable, unwrappedName: "bar" }, 
    { id: 1, name: ScalarObservable, unwrappedName: "foo" }, 
    { id: 3, name: ScalarObservable, unwrappedName: "jazz" } 
] 

Bitte lassen Ich weiß, wenn Sie Fragen zu diesem Code haben.

+0

Super, vielen Dank! Dieses Beispiel hat nicht funktioniert (ohne einen Fehler zu verursachen!), Da compareFn vor der Verwendung deklariert werden muss. – sclausen

+0

Gern geschehen. Ich reorganisiere den Code, beginnend mit der 'compareFn' Deklaration. – AngularChef

0

Sie können Observable.map verwenden. Zum Beispiel:

Observable<Thing[]> things; 
sortedThings$ = things.map(items => items.sort()) // Use your own sort function here. 

in Ihrer Vorlage:

<ul> 
    <li *ngFor="let thing of sortedThings$ | async"> 
    {{thing.name}} <!--No need async pipe here. --> 
    </li> 
</ul> 
+0

Leider ist dies nicht hilfreich, da ich mich für dieses wichtige Detail interessiere, wie man auf einem beobachtbaren Feld sortiert. – sclausen

+0

@Phosphoros. Dein Kommentar ist nicht sehr klar. Mir scheint, dass Tuong Le genau die Frage beantwortet hat, die du gestellt hast. Seien Sie spezifischer, wenn Sie denken, dass seine Antwort nicht den Trick macht. – AngularChef

+0

@AngularFrance "Ich möchte eine Liste von Dingen nach einem beobachtbaren Feld sortieren [...]" ist das nicht klar genug?Das beobachtbare Feld zum Sortieren ist das Problem. – sclausen

0

Wenn ich Sie richtig verstehe, Sie wollen ein Objekt haben, die wie folgt aussieht:

Thing { 
    name: string; 
} 

Sie dann wollen, müssen habe ein Observable, das auf Array von hält:

things$: Observable<Thing[]>; 

Sie möchten dann Ihre Sachen in der thing array durch eine Eigenschaft, in diesem Fall name sortieren.

... 

let sorted$: Observable<Thing[]> = things$.map(items => items.sort(this.sortByName)) 

... 

sortByName(a,b) { 
    if (a.name < b.name) 
    return -1; 
    if (a.name > b.name) 
    return 1; 
    return 0; 
} 

... 

Und dann schließlich, wie Toung Le zeigte in seiner Antwort, ändern Sie Ihre Vorlage wie folgt aus:: Das könnte so gemacht werden

<ul> 
    <li *ngFor="let thing of sorted$ | async"> 
    {{thing.name}} <!--No need async pipe here. --> 
    </li> 
</ul> 
+0

Vielen Dank für die ausführliche Antwort, aber das Namensfeld, das ich sortieren möchte, ist kein String, sondern ein Observable , da dieses Feld in der Datenbank geändert werden kann und dann automatisch aktualisiert wird. – sclausen

+0

@Phosphoros, hmm, das klingt immer noch seltsam für mich. Können Sie Ihre Frage vielleicht aktualisieren, um uns zu zeigen, wie die Daten aussehen, an denen Sie arbeiten? –

Verwandte Themen