Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 rxjs sort (observable) list of objects by an observable field

Tags:

I want to sort a list of things by an observable field, but can't wrap my head around observables to get this working. Has somebody an idea how to achieve this?

The initial situation is something like the following:

Thing[] things;

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

Since I obviously haven't described my problem properly: The field I want to sort the list of things on is an Observable, not a plain string. I want to keep the field updated via websockets so to detect the changes properly I have to use an Observable field on which I can subscribe.

like image 227
sclausen Avatar asked Feb 13 '17 12:02

sclausen


1 Answers

Thanks for clarifying the question, Phosphoros. :)

Here's how you could do what you asked:

// 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 emitted values to the console will show an array of Thing objects sorted by their unwrappedName property:

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

Please let me know if you have questions about this code.

like image 50
AngularChef Avatar answered Sep 18 '22 08:09

AngularChef