Angular2 rxjs由可观察字段排序(可观察)对象列表

scl*_*sen 10 sorting observable rxjs angular

我想通过一个可观察的字段对事物列表进行排序,但不能将我的头围绕在可观察的区域以使其工作.有人知道如何实现这一目标吗?

最初的情况如下:

Thing[] things;

interface Thing {
  name: Observable<string>
}
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li *ngFor="const thing for things">
    {{thing.name | async}}
  </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

因为我显然没有正确描述我的问题:我想要对事物列表进行排序的字段是Observable,而不是普通的字符串.我想通过websockets更新字段,以便正确检测更改我必须使用我可以订阅的Observable字段.

Ang*_*hef 21

谢谢你澄清这个问题,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();
Run Code Online (Sandbox Code Playgroud)

将发出的值记录到控制台将显示按其unwrappedName属性排序的Thing对象数组:

[
  { id: 2, name: ScalarObservable, unwrappedName: "bar" },
  { id: 1, name: ScalarObservable, unwrappedName: "foo" },
  { id: 3, name: ScalarObservable, unwrappedName: "jazz" }
]
Run Code Online (Sandbox Code Playgroud)

如果您对此代码有疑问,请与我们联系.


Fre*_*din 10

如果我理解正确,您希望有一个如下所示的对象:

Thing {
   name: string;
}
Run Code Online (Sandbox Code Playgroud)

然后你想要一个包含在数组上的Observable Thing:

things$: Observable<Thing[]>;
Run Code Online (Sandbox Code Playgroud)

然后,您希望在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;
}

...
Run Code Online (Sandbox Code Playgroud)

最后,就像Toung Le在他的回答中所示,改变你的模板:

<ul>
  <li *ngFor="let thing of sorted$ | async">
    {{thing.name}} <!--No need async pipe here. -->
  </li>
</ul>
Run Code Online (Sandbox Code Playgroud)


Tuo*_* Le 5

您可以使用Observable.map。例如:

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

在您的模板中:

<ul>
  <li *ngFor="let thing of sortedThings$ | async">
    {{thing.name}} <!--No need async pipe here. -->
  </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

  • 嗯,逐字重复这个问题并不能使它变得更清楚。另外,请记住这里的每个人都在贡献自己的时间和知识来尝试帮助您。如果我们中的一些人不理解问题本身,那么提供澄清会更有帮助,即使您可能已经很清楚了。 (6认同)