如何在Angular组件中按日期(asc或desc)排序Observable

时间:2019-11-10 00:10:32

标签: angular rxjs observable

我想知道如何按日期对组件中数组中的数据进行排序,我具有以下结构:

模板:

<div>
  <button (click)="sortByDate()">
    Sort by date
  </button>
</div>
<div *ngFor="let rally of rallies$ | async">
    <img src="{{ rally.icon }}" />
</div>

组件:

rallies$: Observable<Rally>;

  constructor(private ralliesService: RalliesService) {}

  ngOnInit() {
    this.getRallies();
  }

  getRallies() {
    this.rallies$ = this.ralliesService.getRallies();
  }

  sortRalliesByDate() {
    ???
  }

问题是,我了解了订阅可观察对象后如何使用组件中的数组进行操作,但是现在我想直接在可观察对象中进行操作并使用模板中的异步管道。

3 个答案:

答案 0 :(得分:1)

假设您要按属性createdAt进行排序,则可以像这样简单地映射它:

sortRalliesByDate() {
  return this.rallies$
    .pipe(
      map(rallies => rallies.sort((a, b) => a.createdAt - b.createdAt)
    );
}

答案 1 :(得分:0)

您需要参考使用as运算符从可观察对象发出的值。然后,您可以将其传递给sort函数。

<ng-container *ngIf="rallies$ | async as rallies">
  <div>
    <button (click)="sortByDate(rallies)">
      Sort by date
    </button>
  </div>
  <div *ngFor="let rally of rallies">
      <img src="{{ rally.icon }}" />
  </div>
</ng-container>

并使sort函数将模板变量作为参数。

sortByDate = rallies => rallies.sort((a, b) => a.date - b.date);

此解决方案的问题是,您正在突变由可观察到的rallies $发出的rallies。我使用了一个克隆管道,该管道在分配给模板变量之前先克隆发射的值。

*ngIf="rallies$ | async | clone as rallies"

这种排序功能不会引起任何副作用。

import { Pipe, PipeTransform } from '@angular/core';

import { clone } from './clone';

@Pipe({
  name: 'clone'
})
export class ClonePipe implements PipeTransform {

  transform(value: any): any {
    return clone(value);
  }
}

和克隆功能

export const clone = (obj: any) =>
  Array.isArray(obj)
    ? obj.map(item => clone(item))
    : obj instanceof Date
    ? new Date(obj.getTime())
    : obj && typeof obj === 'object'
    ? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
        o[prop] = clone(obj[prop]);
        return o;
      }, {})
    : obj;

克隆意味着我们不会对其他组件产生任何副作用,这些其他组件可能正在使用可观察到的反弹数据。

答案 2 :(得分:0)

最终以这种方式解决:

sortRalliesByDateDesc() {
        this.rallies$ = this.rallies$.pipe(map((rallies => rallies.sort((a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime()))))
}

  sortRalliesByDateAsc() {
        this.rallies$ = this.rallies$.pipe(map((rallies => rallies.sort((a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime()))))
}

Stackblitz示例:

https://stackblitz.com/edit/angular-glwwvv