2017-02-13 4 views
0

관찰 가능 필드에 의해 사물 목록을 정렬하고 싶지만 관찰 가능 객체 주위로 머리를 감싸서이 작업을 수행 할 수는 없습니다. 누군가이 아이디어를 어떻게 달성 했습니까?angular2 rxjs 관찰 가능 필드에 의한 객체 목록 (observable)

초기 상황은 다음과 같습니다.

Thing[] things; 

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

편집 : 나는 분명히 설명하지 않았으므로 제대로 내 문제 : 나는 물건의 목록을 정렬 할 필드는 관찰 가능한 아닌 일반 문자열입니다. 필드를 업데이트하여 웹 소켓을 통해 업데이트 된 상태로 유지하여 변경 사항을 제대로 감지 할 수 있도록 Observable 필드를 사용해야합니다.

+0

Observable 으로 이름을 지정하는 이유는 무엇입니까? 난 당신이 정상적인 문자열로 그 속성을두고 싶다고 생각합니다 –

+0

내가 관찰 할 수있는 필드로 사용하고 싶습니다, 그 값은 런타임에 변경할 수 있기 때문에. – sclausen

+0

Phosphoros, 당신은'name'이나'Thing'에 가입하지 않고, (Observable ') –

답변

5

감사를 질문 Phosphoros을 명확히하십시오.

// 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(); 

로깅 방출 값을 콘솔에 자신의 unwrappedName 재산으로 분류 것은 객체의 배열이 표시됩니다 :

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

주시기 바랍니다 :)를 여기

는 질문 당신이 할 수있는 방법 이 코드에 대해 궁금한 점이 있으면 알려드립니다.

+0

대단히 감사합니다! compareFn은 사용하기 전에 선언해야하기 때문에이 예제는 효과가 없었습니다 (오류를 던지지 않고!). – sclausen

+0

반갑습니다. 'compareFn' 선언으로 시작하는 코드를 재구성 할 것입니다. – AngularChef

0

Observable.map을 사용할 수 있습니다. 예를 들어

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

:

Thing { 
    name: string; 
} 

그런 다음 원하는 한 : 내가 제대로 이해하면,이처럼 보이는 개체를 갖고 싶어

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

유감스럽게도이 부분은 유용하지 않습니다. 왜냐하면이 핵심적인 세부 사항에 관심이 있고, 관찰 가능한 필드를 정렬하는 방법을 알고 있기 때문입니다. – sclausen

+0

@ Phosphoros. 귀하의 의견은 명확하지 않습니다. 나에게 Tuong Le가 당신이 묻는 질문에 정확히 답한 것처럼 보입니다. 그의 대답이 트릭을하지 않는다고 생각한다면 좀 더 자세하게 설명하십시오. – AngularChef

+0

@AngularFrance "관찰 할 수있는 필드로 목록을 정렬하고 싶습니다. [...]"충분히 명확하지 않습니까?관찰 할 수있는 필드가 문제입니다. – sclausen

0

배열이 Thing 인 관찰 대상이 있습니다.

things$: Observable<Thing[]>; 

그런 다음 속성으로 에서 항목을 정렬하려고합니다. 즉 다음과 같이 할 수있다 : 마지막으로 다음

... 

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

... 

그리고를 Toung 르처럼 같은 템플릿을 변경, 그의 대답에 보여 주었다 :

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

많은 답변을 주신 데 대해 감사드립니다. 이름 필드는 문자열이 아니지만 Observable 입니다.이 필드는 데이터베이스에서 변경 될 수 있으며 자동으로 업데이트됩니다. – sclausen

+0

@Phosphoros, 음, 아직도 이상하게 들리네. 질문을 업데이트하여 현재 작업중인 데이터가 어떻게 보이는지 확인할 수 있습니까? –

관련 문제