Mat-sort avec rxjs ne fonctionne pas correctement

j'ai le problème avec l'implémentation mat-sort dans mat-table, quand la source a été créée à partir de observers stream.

Simplement de la mise en œuvre par l'intermédiaire de la documentation par:

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

ne fonctionne pas correctement - sera toujours triés seulement 5 lignes sur ma table.

je pense, mon problème est avec l'utilisation correcte avec la connexion rxjs.

malheureusement, après avoir vérifié une autre question / documentation Je ne trouve aucune idée.

j'ai généré les données source: flux de deux observateurs. J'ai aussi utilisé pour It BehaviourSubject (pour les valeurs initiales), combineLatest et switch map. Tableau a été créé correctement et fonctionne parfaitement.

<!-Aussi quand j'ai ajouté le filtre (selon la documentation de conception du matériau angulaire) fonctionne correctement. Mais des tapis de tri... pas (seulement 5 premières lignes).

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));
    }

J'ai aussi essayé avec Observable.zip - mais je pense que c'est pas mon cas. Toute idée / Conseil sera très précieux.

je pense, je devrait souscrire la méthode de tri aux flux observables. Même problème que j'ai avec la pagination. Parfois fonctionne, parfois pas.

12
demandé sur profiler 2018-08-20 14:25:35

1 réponses

votre code de question ressemble à l'exemple des tables mat qui affichent les données des appels HTTP: https://stackblitz.com/angular/rmoxkmpkkyj?file=app%2Ftable-http-example.ts

je pense que l'implémentation peut être simplifiée en traitant la pagination et en triant les événements séparément.

veuillez jeter un coup d'oeil à cet exemple I build qui rafraîchit les données sur chaque événement: https://stackblitz.com/edit/angular-material-mat-table-sort-merge-streams?file=src%2Fapp%2Fmy-books%2Fmy-books.component.ts

Les gestionnaires d'Événements

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());
    });

}

La méthode pour récupérer les options d'affichage

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

    return options;
  }

Un exemple de comment fusionner plusieurs flux

  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;
  }

Voir le code complet ici: https://stackblitz.com/edit/angular-material-mat-table-sort-merge-streams?file=src%2Fapp%2Fbooks.service.ts

1
répondu hamilton.lima 2018-08-28 14:47:53