web-dev-qa-db-ja.com

監視可能なフィールドによるオブジェクトのAngular2 rxjsソート(監視可能)リスト

オブザーバブルフィールドで物事のリストを並べ替えたいのですが、これを機能させるためにオブザーバブルに頭を包むことはできません。誰かがこれを達成する方法を考えていますか?

最初の状況は次のようなものです。

Thing[] things;

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

私は明らかに自分の問題を適切に説明していないので、物事のリストをソートしたいフィールドは、単なる文字列ではなく、Observableです。変更を適切に検出するために、サブスクライブ可能なObservableフィールドを使用する必要があるため、websocketsを介してフィールドを更新し続ける必要があります。

10
sclausen

質問を明確にしてくれてありがとう、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プロパティでソートされたThingオブジェクトの配列が表示されます。

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

このコードについて質問がある場合はお知らせください。

16
AngularChef

私があなたを正しく理解していれば、次のようなオブジェクトが必要です。

Thing {
   name: string;
}

次に、Thingの配列を保持するObservableが必要です。

things$: Observable<Thing[]>;

次に、thing array内のプロパティをプロパティ(この場合はname)でソートします。これは次のように実行できます。

...

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 Leが彼の答えで示したように、テンプレートを次のように変更します:

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

Observable.mapを使用できます。例えば:

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

テンプレートで:

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

_Observable.map_を使用し、localeComparesort()を使用できます。これは次のようになります。

_.map(data => ({
        label: data.name
}))
.sort((a, b) => a.label.localeCompare(b.label));
_
2
Laurie Clark

groupby演算子を使用(再生 with it ):

const $things = getThings();

$things.pipe(
    groupBy(thing => thing.id),
    mergeMap(group$ => group$.pipe(
        reduce((acc, cur) =>[...acc, cur], [])
    ))
)
.subscribe(console.log)

Groupby docs

0
Luillyfe