web-dev-qa-db-fra.com

Mat-sort avec rxjs ne fonctionne pas correctement

J'ai le problème d'implémenter mat-sort dans mat-table, lorsque la source a été créée à partir du flux d'observateurs.

Il suffit de le mettre en œuvre via la documentation en:

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

ne fonctionne pas correctement - seront toujours triés que 5 lignes sur ma table.

Je pense, mon problème est avec la bonne utilisation avec la connexion rxjs.

Malheureusement, après avoir vérifié d'autres questions/documentation, je ne trouve aucune idée.

J'ai généré une source de données à partir de deux flux d'observateurs. J'ai aussi utilisé pour cela BehaviourSubject (pour les valeurs initiales), combineLatest et switch map. La table a été créée correctement et fonctionne parfaitement.

De plus, lorsque j'ai ajouté le filtre (selon la documentation de conception du matériau angulaire), il fonctionne correctement. Mais mat-sort ... 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 ce n'est pas non plus mon cas. Toute idée/conseil sera très précieux.

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

12
profiler

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

Je pense que l'implémentation peut être simplifiée en gérant les événements de pagination et de tri séparément. 

Veuillez regarder cet exemple que je construis 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 obtenir les options d'affichage en cours 

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

    return options;
  }

Exemple de fusion de 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
hamilton.lima