如何在我自己的 Angular 数据表中实现过滤? [英] How to implement filtering in my own DataTable in Angular?

查看:26
本文介绍了如何在我自己的 Angular 数据表中实现过滤?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用过滤器时遇到问题.我决定实现我的个人数据源而不使用 MatTableDataSource,因此我没有可用的过滤器方法.我可以从 HTML 捕获事件,然后将其传递给组件,然后从组件将其传递给数据源.唯一的问题是,即使接收到过滤器,表也不会更新,就好像没有我不知道如何实现的事件发射器一样.例如,如果我插入过滤器并更改页面顺序,过滤器将起作用.我会发布代码以获得更好的外观,我很抱歉发音

数据模型

import { Sistema } from './sistema'出口类 Galassia {身份证号码;名称:字符串;imgLink:字符串;系统:系统[];}

service-rest.ts

import { Injectable } from '@angular/core';从'@angular/common/http' 导入 { HttpClient };import { Observable, of } from 'rxjs';从 '../model/galassia' 导入 { Galassia };import { catchError, tap } from 'rxjs/operators';@Injectable({提供在:'根'})导出类 ServizioProdottiRESTService {加拉西:加拉西[];prodottiUrl = 'http://localhost:8080/prodotti';构造函数(私有http:HttpClient){}getGalassie(): Observable{返回 this.http.get(this.prodottiUrl + '/galassie').pipe(点击(星系 => this.galassie = 星系),catchError(this.handleError('getGalassie', [])));}私有句柄错误(操作 = '操作',结果?:T){返回(错误:任何):Observable=>{控制台日志(错误);this.log(`${operation} 失败:${error.message}`);返回(结果为 T);};}私人日志(消息:字符串){console.log('HeroService: ' + message);}}

component.ts

import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';从 '@angular/material/paginator' 导入 { MatPaginator };从'@angular/material/sort'导入{MatSort};从'@angular/material/table'导入{MatTable};从 './lista-prodotti-datasource' 导入 { ListaProdottiDataSource };从'../servizio-prodotti-rest.service'导入{ServizioProdottiRESTService};从 '../../model/galassia' 导入 { Galassia };@成分({选择器:'app-lista-prodotti',templateUrl: './lista-prodotti.component.html',styleUrls: ['./lista-prodotti.component.css']})导出类 ListaProdottiComponent 实现 AfterViewInit、OnInit {@ViewChild(MatPaginator) 分页器:MatPaginator;@ViewChild(MatSort) 排序:MatSort;@ViewChild(MatTable) 表:MatTable<Galassia>;数据源:ListaProdottiDataSource;displayColumns = ['imgLink','nome', 'button'];构造函数(私有 myService:ServizioProdottiRESTService){}ngOnInit() {this.dataSource = new ListaProdottiDataSource(this.myService);}ngAfterViewInit() {this.table.dataSource = this.dataSource;this.dataSource.sort = this.sort;this.dataSource.paginator = this.paginator;}应用过滤器(事件:事件){const filterValue = (event.target as HTMLInputElement).value;this.dataSource.filter = filterValue.trim().toLowerCase();}}

component.html

<mat-form-field><input matInput (keyup)="applyFilter($event)" placeholder="Ex.ium"></mat-form-field>

<div class="mat-elevation-z8 table"><table mat-table class="full-width-table" matSort aria-label="Elements".[dataSource]="dataSource.data"><!-- imgLink 列--><ng-container matColumnDef="imgLink"><th mat-h​​eader-cell *matHeaderCellDef mat-sort-header>Img</th><td mat-cell *matCellDef="let row"><img [src]="row.imgLink"/></td></ng-容器><!-- 名称列--><ng-container matColumnDef="nome"><th mat-h​​eader-cell *matHeaderCellDef mat-sort-header>Nome</th><td mat-cell *matCellDef="let row">{{row.nome}}</td></ng-容器><!-- 按钮列--><ng-container matColumnDef="button"><th mat-h​​eader-cell *matHeaderCellDef mat-sort-header>按钮</th><td mat-cell *matCellDef="let row"><button mat-raised-button color="primary">Scegli ></button></td></ng-容器><tr mat-h​​eader-row *matHeaderRowDef="displayedColumns"></tr><tr mat-row *matRowDef="let row; columns:displayedColumns;"></tr><mat-paginator #paginator[length]="dataSource?.data.length"[页面索引]="0"[页面大小]="5"[pageSizeOptions]="[5, 10, 15]"></mat-paginator>

和 datasource.ts

import { DataSource } from '@angular/cdk/collections';从'@angular/material/paginator'导入{MatPaginator};从'@angular/material/sort'导入{MatSort};从'rxjs/operators'导入{地图};import { Observable, of as observableOf, merge } from 'rxjs';从'../servizio-prodotti-rest.service'导入{ServizioProdottiRESTService};从'../../model/galassia'导入{加拉西亚};导出类 ListaProdottiDataSource 扩展了 DataSource<Galassia>{数据:加拉西亚[];分页器:MatPaginator;排序:MatSort;过滤器:字符串;构造函数(私有 myService:ServizioProdottiRESTService){极好的();this.myService.getGalassie().subscribe(galaxy => this.data = Galaxy);}连接():可观察的<Galassia[]>{常量数据突变 = [observableOf(this.data),this.paginator.page,this.sort.sortChange];return merge(...dataMutations).pipe(map(() => {返回 this.getFilteredData(this.getPagedData(this.getSortedData([...this.data])));}));}断开连接(){}私人 getFilteredData(数据:Galassia[]){返回 data.filter(d => d.nome.toLowerCase() == this.filter);}私人 getPagedData(数据:Galassia[]){const startIndex = this.paginator.pageIndex * this.paginator.pageSize;返回 data.splice(startIndex, this.paginator.pageSize);}私人 getSortedData(数据:Galassia[]){if (!this.sort.active || this.sort.direction === '') {返回数据;}返回 data.sort((a, b) => {const isAsc = this.sort.direction === 'asc';开关(this.sort.active){case 'nome': return compare(a.nome, b.nome, isAsc);默认值:返回 0;}});}}function compare(a: string | number, b: string | number, isAsc: boolean) {返回 (a < b ? -1 : 1) * (isAsc ? 1 : -1);}

解决方案

如果我关于过滤器不会在您的连接中触发任何新的可观察对象的评论是正确的,您可以使用以下内容:

import { DataSource } from '@angular/cdk/collections';从'@angular/material/paginator'导入{MatPaginator};从'@angular/material/sort'导入{MatSort};从'rxjs/operators'导入{地图};import { Observable, of as observableOf, merge, BehaviorSubject } from 'rxjs';从'../servizio-prodotti-rest.service'导入{ServizioProdottiRESTService};从 '../../model/galassia' 导入 { Galassia };导出类 ListaProdottiDataSource 扩展了 DataSource<Galassia>{数据:加拉西亚[];分页器:MatPaginator;排序:MatSort;get filter(): string { return this.filter$.getValue();}设置过滤器(值:字符串){ this.filter$.next(value);}过滤器$:行为主题<字符串>= new BehaviorSubject(null);构造函数(私有 myService:ServizioProdottiRESTService){极好的();this.myService.getGalassie().subscribe(galaxy => this.data = Galaxy);}连接():可观察的<Galassia[]>{常量数据突变 = [observableOf(this.data),this.paginator.page,this.sort.sortChange,this.filter$];return merge(...dataMutations).pipe(map(() => {返回 this.getFilteredData(this.getPagedData(this.getSortedData([...this.data])));}));}断开连接(){}私人 getFilteredData(数据:Galassia[]){返回 data.filter(d => d.nome.toLowerCase() == this.filter);}私人 getPagedData(数据:Galassia[]){const startIndex = this.paginator.pageIndex * this.paginator.pageSize;返回 data.splice(startIndex, this.paginator.pageSize);}私人 getSortedData(数据:Galassia[]){if (!this.sort.active || this.sort.direction === '') {返回数据;}返回 data.sort((a, b) => {const isAsc = this.sort.direction === 'asc';开关(this.sort.active){case 'nome': return compare(a.nome, b.nome, isAsc);默认值:返回 0;}});}}function compare(a: string | number, b: string | number, isAsc: boolean) {返回 (a < b ? -1 : 1) * (isAsc ? 1 : -1);}

I'm having problems with filters. I decided to implement my personal datasource and not to use the MatTableDataSource and therefore I don't have the filter method available. I can capture the event from the HTML and then pass it to the component and from the component pass it to the datasource. The only problem is that even if the filter is received, the table does not update as if there were no event emitter that I don't know how to implement. For example, if I insert the filter and change the page order, the filter works. I'll post the code to get a better look and I'm sorry for the pronunciation

data model

import { Sistema } from './sistema'

export class Galassia {

  id: number;
  nome: string;
  imgLink: string;
  sistema: Sistema[];

}

service-rest.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { Galassia } from '../model/galassia';
import { catchError, tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ServizioProdottiRESTService {


  galassie: Galassia[];

  prodottiUrl = 'http://localhost:8080/prodotti';

  constructor(private http: HttpClient) { }

  getGalassie(): Observable<Galassia[]> {
    return this.http.get<Galassia[]>(this.prodottiUrl + '/galassie').pipe(
    tap(galaxy => this.galassie = galaxy),
    catchError(this.handleError('getGalassie', []))
  );
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
        console.log(error);
        this.log(`${operation} failed: ${error.message}`);
        return of(result as T);
    };
  }

  private log(message: string) {
    console.log('HeroService: ' + message);
  }
}

component.ts

import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable } from '@angular/material/table';
import { ListaProdottiDataSource } from './lista-prodotti-datasource';
import { ServizioProdottiRESTService } from '../servizio-prodotti-rest.service';
import { Galassia } from '../../model/galassia';

@Component({
  selector: 'app-lista-prodotti',
  templateUrl: './lista-prodotti.component.html',
  styleUrls: ['./lista-prodotti.component.css']
})
export class ListaProdottiComponent implements AfterViewInit, OnInit {

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatTable) table: MatTable<Galassia>;

  dataSource: ListaProdottiDataSource;
  displayedColumns = ['imgLink' ,'nome', 'button'];

  constructor(private myService: ServizioProdottiRESTService) {}

  ngOnInit() {
    this.dataSource = new ListaProdottiDataSource(this.myService);
  }

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

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();
  }
}

component.html

<div class="example-header">
  <mat-form-field>
    <input matInput (keyup)="applyFilter($event)" placeholder="Ex. ium">
  </mat-form-field>
</div>

<div class="mat-elevation-z8 table">

  <table mat-table class="full-width-table" matSort aria-label="Elements".[dataSource]="dataSource.data">

    <!-- imgLink Column -->
    <ng-container matColumnDef="imgLink">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Img</th>
      <td mat-cell *matCellDef="let row"><img [src]="row.imgLink"/></td>
    </ng-container>

    <!-- Name Column -->
    <ng-container matColumnDef="nome">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Nome</th>
      <td mat-cell *matCellDef="let row">{{row.nome}}</td>
    </ng-container>

    <!-- Button Column -->
    <ng-container matColumnDef="button">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Button</th>
      <td mat-cell *matCellDef="let row"><button mat-raised-button color="primary">Scegli ></button></td>
    </ng-container>

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

  <mat-paginator #paginator
      [length]="dataSource?.data.length"
      [pageIndex]="0"
      [pageSize]="5"
      [pageSizeOptions]="[5, 10, 15]">
  </mat-paginator>
</div>

and datasource.ts

import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge } from 'rxjs';
import { ServizioProdottiRESTService } from '../servizio-prodotti-rest.service';
import { Galassia } from '../../model/galassia';


export class ListaProdottiDataSource extends DataSource<Galassia> {

  data: Galassia[];
  paginator: MatPaginator;
  sort: MatSort;
  filter: string;

  constructor(private myService: ServizioProdottiRESTService) {
    super();
    this.myService.getGalassie().subscribe(galaxy => this.data = galaxy);
  }


  connect(): Observable<Galassia[]> {

    const dataMutations = [
      observableOf(this.data),
      this.paginator.page,
      this.sort.sortChange
    ];

    return merge(...dataMutations).pipe(map(() => {
      return this.getFilteredData(this.getPagedData(this.getSortedData([...this.data])));
    }));
  }

  disconnect() {}

  private getFilteredData(data: Galassia[]) {

    return data.filter(d => d.nome.toLowerCase() == this.filter);
  }

  private getPagedData(data: Galassia[]) {
    const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
    return data.splice(startIndex, this.paginator.pageSize);
  }

  private getSortedData(data: Galassia[]) {
    if (!this.sort.active || this.sort.direction === '') {
      return data;
    }

    return data.sort((a, b) => {
      const isAsc = this.sort.direction === 'asc';
      switch (this.sort.active) {
        case 'nome': return compare(a.nome, b.nome, isAsc);
        default: return 0;
      }
    });
  }
}

function compare(a: string | number, b: string | number, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

解决方案

If my comment is correct about the filter not trigging any new observables in your connect, you could use something maybe like this:

import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge, BehaviorSubject } from 'rxjs';
import { ServizioProdottiRESTService } from '../servizio-prodotti-rest.service';
import { Galassia } from '../../model/galassia';


export class ListaProdottiDataSource extends DataSource<Galassia> {

  data: Galassia[];
  paginator: MatPaginator;
  sort: MatSort;
  get filter(): string { return this.filter$.getValue(); }
  set filter(value: string) { this.filter$.next(value); }
  filter$: BehaviorSubject<string> = new BehaviorSubject<string>(null);

  constructor(private myService: ServizioProdottiRESTService) {
    super();
    this.myService.getGalassie().subscribe(galaxy => this.data = galaxy);
  }


  connect(): Observable<Galassia[]> {

    const dataMutations = [
      observableOf(this.data),
      this.paginator.page,
      this.sort.sortChange,
      this.filter$
    ];

    return merge(...dataMutations).pipe(map(() => {
      return this.getFilteredData(this.getPagedData(this.getSortedData([...this.data])));
    }));
  }

  disconnect() {}

  private getFilteredData(data: Galassia[]) {

    return data.filter(d => d.nome.toLowerCase() == this.filter);
  }

  private getPagedData(data: Galassia[]) {
    const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
    return data.splice(startIndex, this.paginator.pageSize);
  }

  private getSortedData(data: Galassia[]) {
    if (!this.sort.active || this.sort.direction === '') {
      return data;
    }

    return data.sort((a, b) => {
      const isAsc = this.sort.direction === 'asc';
      switch (this.sort.active) {
        case 'nome': return compare(a.nome, b.nome, isAsc);
        default: return 0;
      }
    });
  }
}

function compare(a: string | number, b: string | number, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

这篇关于如何在我自己的 Angular 数据表中实现过滤?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆