Каков наилучший способ реализовать сортировку и фильтрацию в динамической html-таблице начальной загрузки в angular 7? - PullRequest
0 голосов
/ 13 июня 2019

Я хочу реализовать сортировку и фильтрацию в таблице по углам 7. Является ли хорошей идеей использовать некоторые доступные решения, такие как угловые материалы, или построить трубу для легкой сортировки и фильтрации.

1 Ответ

0 голосов
/ 13 июня 2019

Я оказался в такой ситуации, я уже использовал угловой материал, поэтому решил продолжить.

Вот так я обработал поиск и сортировку таблицы

Я создал класс класса источника данных для обработки данных http, внутри него я вызываю службу, которая делает запрос данных http

import {Domanda} from '../models';
import {DataSource} from '@angular/cdk/table';
import {BehaviorSubject, Observable, of} from 'rxjs';
import {catchError, finalize} from 'rxjs/operators';
import {CollectionViewer} from '@angular/cdk/collections';
import {ApiService} from './api.service';


export class ListaDomandeDatasource implements DataSource<Domanda> {

  private domandeSubject = new BehaviorSubject<Domanda[]>([]);


// Gestisce il caricamento della tabella
  private loadingSubject = new BehaviorSubject<boolean>(false);

  public loading$ = this.loadingSubject.asObservable();

  constructor(private apiService: ApiService) {

  }

  cercaDomande(idConcorso: number,
               keywords: string,
               sortOrder: string,
               pageIndex: number,
               pageSize: number) {

    this.loadingSubject.next(true);

    this.apiService.cercaDomande(idConcorso, keywords, sortOrder,
      pageIndex, pageSize).pipe(
      catchError(() => of([])),
      finalize(() => this.loadingSubject.next(false))
    )
      .subscribe(lessons => this.domandeSubject.next(lessons));

  }

  connect(collectionViewer: CollectionViewer): Observable<Domanda[]> {
    console.log('Connecting data source');
    return this.domandeSubject.asObservable();
  }

  disconnect(collectionViewer: CollectionViewer): void {
    this.domandeSubject.complete();
    this.loadingSubject.complete();
  }

}

В компоненте, где определена таблица, я просто играю с rxjs, чтобы прослушивать ввод, но на самом деле логическая часть - все это делает бэкэнд.

import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {Concorso} from '../../../../core/models';
import {MatPaginator, MatSort} from '@angular/material';
import {ActivatedRoute, Router} from '@angular/router';
import {ApiService} from '../../../../core/services';
import {ListaDomandeDatasource} from '../../../../core/services/lista-domande.datasource';
import {fromEvent, merge} from 'rxjs';
import {debounceTime, distinctUntilChanged, tap} from 'rxjs/operators';

@Component({
  selector: 'app-lista-domande',
  templateUrl: './concorso.component.html',
  styleUrls: ['./concorso.component.scss']
})
export class ConcorsoComponent implements OnInit, AfterViewInit {
  nomeColonne: string[] = ['id', 'nominativo', 'dataNascita', 'dataProva', 'nomeProva', 'open'];

  dataSource: ListaDomandeDatasource;
  concorso: Concorso; // Risultato del resolver esistenza concorso


  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
  @ViewChild(MatSort, { static: true }) sort: MatSort;
  @ViewChild('input', { static: true }) input: ElementRef;

  constructor(private api: ApiService,
              private router: Router,
              private route: ActivatedRoute) {

  }


  ngOnInit() {

    /* Se si resta sulla stessa pagina e si cambiano solo i parametri la pagina non viene ricaricata, dunque ngOnInit non viene triggerato,
    * per ovviare a ciò resto in ascolto dei parametri che cambiano e chiamo la lista delle domande */
    this.route.params.subscribe(
      () => {
        this.concorso = this.route.snapshot.data.concorso;
      }
    );

    // Istanzio il datasource passandogli il service
    this.dataSource = new ListaDomandeDatasource(this.api);

    this.dataSource.cercaDomande(this.concorso.id, '', 'asc', 0, 3);

  }

  ngAfterViewInit() {

    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);

    // Triggero evento input nella searchbar
    fromEvent(this.input.nativeElement, 'keyup')
      .pipe(
        debounceTime(150),
        distinctUntilChanged(),
        tap(() => {
          this.paginator.pageIndex = 0;

          this.CaricaPaginaDomande();
        })
      )
      .subscribe();

    merge(this.sort.sortChange, this.paginator.page)
      .pipe(
        tap(() => this.CaricaPaginaDomande())
      )
      .subscribe();

  }

  CaricaPaginaDomande() {
    this.dataSource.cercaDomande(
      this.concorso.id,
      this.input.nativeElement.value,
      this.sort.direction,
      this.paginator.pageIndex,
      this.paginator.pageSize);
  }

  GotoDomanda(id) {
    return 'domanda/' + id;
  }

}

И это HTML-часть:

<h2>CONCORSO: {{concorso.id}}</h2>

<div fxLayout="column">


  <mat-form-field>
    <label for="searchbar"></label>
    <input matInput id="searchbar" placeholder="Cerca candidato per il suo identificativo" #input>
    <mat-icon matPrefix>search</mat-icon>
  </mat-form-field>


  <div class="spinner-container" *ngIf="dataSource.loading$ | async">
    <mat-spinner></mat-spinner>
  </div>

  <table fxFill
         mat-table [dataSource]="dataSource"
         matSort matSortActive="created" matSortDisableClear matSortDirection="asc">

    <!-- Colonna id domande-->
    <ng-container matColumnDef="id">
      <th mat-header-cell *matHeaderCellDef>#</th>
      <td mat-cell *matCellDef="let row">{{row.DomandaConcorso.IdDomanda}}</td>
    </ng-container>

    <!-- Colonna cognome nome canditato -->
    <ng-container matColumnDef="nominativo">
      <th mat-header-cell *matHeaderCellDef>Nominativo</th>
      <td mat-cell *matCellDef="let row">{{row.Anagrafica.Cognome}} {{row.Anagrafica.Nome}}</td>
    </ng-container>

    <!-- Colonna data di nascita candidato -->
    <ng-container matColumnDef="dataNascita">
      <th mat-header-cell *matHeaderCellDef>Data di nascita</th>
      <td mat-cell *matCellDef="let row">{{row.Anagrafica.DataNascita}}</td>
    </ng-container>

    <!-- Colonna data prova candidato -->
    <ng-container matColumnDef="dataProva">
      <th mat-header-cell *matHeaderCellDef>Data prova</th>
      <td mat-cell *matCellDef="let row">{{row.prove[2].dataProva}}</td>
    </ng-container>

    <!-- Colonna nome ultima prova -->
    <ng-container matColumnDef="nomeProva">
      <th mat-header-cell *matHeaderCellDef>Data prova</th>
      <td mat-cell *matCellDef="let row">{{row.prove[2].nomeProva}}</td>
    </ng-container>


    <!-- Colonna bottone apri singola domande -->
    <ng-container matColumnDef="open">
      <th mat-header-cell *matHeaderCellDef></th>
      <td mat-cell *matCellDef="let row" >
        <button [routerLink]="GotoDomanda(row.DomandaConcorso.IdDomanda)"  mat-flat-button>VISUALIZZA</button>
      </td>
    </ng-container>


    <tr mat-header-row *matHeaderRowDef="nomeColonne"></tr>
    <tr mat-row *matRowDef="let row; columns: nomeColonne;"></tr>
  </table>

  <mat-paginator [length]="20" [pageSize]="3"
                 [pageSizeOptions]="[3, 5, 10]"></mat-paginator>

</div>

Все это невозможно сделать, не прочитав документы с данными: https://material.angular.io/components/categories/tables

Если у вас есть еще вопросы, скажите мне.

...