使用rxjs的Mat-sort无法正常工作

时间:2018-08-20 11:25:36

标签: angular sorting rxjs angular-material angular5

当源是从观察者流创建时,我在mat-table中实现mat-sort有问题。

只需通过以下文档即可实现:

ngAfterViewInit() {
        this.dataSource.sort = this.sort;
    }

工作不正常-在我的表上总是只对5行排序。

我认为,我的问题是与rxjs连接一起正确使用它。

不幸的是,在检查了另一个问题/文档后,我找不到任何想法。

我从两个观察者流生成了数据源。我也使用了BehaviourSubject(用于初始值),combinateLatest和switch映射。表格已正确创建并正常运行。

此外,当我添加过滤器时(根据角度材料设计文档),它也可以正常工作。但是垫子排序...不是(仅5行)。

ngOnInit() {
        this.filters = itemFilters;
        this.idSubject = new BehaviorSubject(this.filters[0]);
        Observable.combineLatest(this.name, this.selectedFilter)
            .do(_ => this.items = null)
            .switchMap(([name, filterIndex]: [Name | null, number]) => {
                const item = this.filters[filterIndex];
                this.namesSubject.next(item.display);
                return this.itemService.getItems(name);
            })
            .subscribe(this.setItems.bind(this), this.setError.bind(this));
    }

我也尝试使用Observable.zip-但我认为这也不是我的情况。任何想法/建议都将非常有价值。

我认为,我应该将排序方法订阅到可观察的流。我在分页时遇到同样的问题。有时有效,有时无效。

1 个答案:

答案 0 :(得分:1)

您的问题代码看起来像显示来自HTTP调用的数据的mat-table中的示例:https://stackblitz.com/angular/rmoxkmpkkyj?file=app%2Ftable-http-example.ts

我认为可以通过分别处理分页和排序事件来简化实现。

请看一下我构建的示例,该示例刷新每个事件的数据:https://stackblitz.com/edit/angular-material-mat-table-sort-merge-streams?file=src%2Fapp%2Fmy-books%2Fmy-books.component.ts

事件处理程序

ngOnInit() {

    // default data 
    this.refresh(this.getDefaultOptions());

    this.sort.sortChange.subscribe((sort: Sort) => {
      console.log('sortChange', this.sort.active);
      this.paginator.pageIndex = 0;
      this.refresh(this.getCurrentOptions());
    });

    this.paginator.page.subscribe((page: PageEvent) => {
      console.log('paginator ', page);
      this.refresh(this.getCurrentOptions());
    });

}

获取当前视图选项的方法

getCurrentOptions() {
    const options: ViewOptions = {
      sortField: this.sort.active,
      sortDirection: this.sort.direction,
      page: this.paginator.pageIndex,
      pageSize: this.paginator.pageSize
    };

    return options;
  }

有关如何合并多个流的示例

  findBooks(options: ViewOptions): Observable<BooksResponse> {

    console.log('findBooks', options);

    // retrieve multiple streams
    const multipleStreams = this.mockMultipleStreams();

    // sort and slice result
    const sortedAndSliced = multipleStreams.pipe(
      tap(items => {
        items = items.sort((a, b) => {
          const sortOrder = options.sortDirection === 'asc' ? -1 : 1;
          const valueA = a[options.sortField];
          const valueB = b[options.sortField];

          var result = (valueA < valueB) ? -1 : (valueA > valueB) ? 1 : 0;
          return result * sortOrder;
        });
      }),
      tap((items: Book[]) => {
        const start = options.page * options.pageSize;
        const end = start + options.pageSize;
        items = items.slice(start, end);
      })
    );

    // wrap in the response object
    const bookResponse = sortedAndSliced.pipe(
      map((items: Book[]) => {
        const response: BooksResponse = {
          items: items,
          total: this.fakeDataLength
        };
        return response;
      })
    );

    return bookResponse;

  }

  mockMultipleStreams(): Observable<Book[]> {
    const third = this.fakeDataLength / 3;

    // merge all the streams together
    const allTheBooks: Observable<[Book[], Book[], Book[]]> = zip(
      of(this.mockBooks('Magazine', third)),
      of(this.mockBooks('Books', third)),
      of(this.mockBooks('Newspaper', third))
    );

    // flatten the data 
    const result = allTheBooks
      .pipe(map((items) => {
        let result: Book[] = [];
        items.forEach(books => {
          books.forEach(book => { result.push(book) })
        });
        return result;
      }));

      return result;
  }

在此处查看完整代码:https://stackblitz.com/edit/angular-material-mat-table-sort-merge-streams?file=src%2Fapp%2Fbooks.service.ts