Филтрирайте MatTableDataSource, като използвате съдържанието на масива

Имам таблица в моето приложение Angular, която показва потребителски данни в своите редове. Искам да мога да филтрирам тази таблица с помощта на масив от низове, които представляват потребителски имейли. Ако имейлът на потребителя съществува в масива, тогава не искам потребителят да се показва в таблицата.

Разгледах филтрирането на материални таблици на Angular, по-специално тук където те използват единичен низ за филтриране на таблицата. Всички примери, които изглежда намирам, също включват използването на единичен низ, например от потребителя, който задава филтърен низ чрез вход.

Въпреки това не мога да намеря никакви решения за използване на масив от низове за филтриране на данните. Трябва ли да свържа целия масив в низ и след това да предам това в свойството filterPredicate?

    applyAddedUserFilter() {
        this._usersService.addedUsers$.subscribe((addedUsers: AddedUser[]) => {
          let addedUserEmails: string[] = addedUsers.map(({ email }) => email);

          this.users.filterPredicate = (user: GoogleUser, filter: string) => { //<-- What exactly do I need to do here to use my string[] to filter my table's results?
            //Unsure what I need to do here.
          }
        });
      }

Освен това, след като имам зададен предикат за филтър, къде трябва да извикам този метод. Достатъчно ли е да можете да извикате метода, след като таблицата е конструирана?


person Jake12342134    schedule 06.08.2019    source източник
comment
може би опитайте нещо подобно: let filteredData = this.users.filter(user => !(addedUserEmails.indexOf(user.email) > -1)); След това можете да го добавите така --› this.dataSource.data = filteredData;   -  person sagat    schedule 06.08.2019
comment
да Бих предложил да направите това вместо filterpredicate и директно да филтрирате масива и да го зададете на datasource.data. Това трябва да работи.   -  person sagat    schedule 06.08.2019
comment
@sagat Можете ли да редактирате оригиналната публикация, за да ми покажете как прилагате това? Ако се опитам да направя this.users.filter(user => !(addedUserEmails.indexOf(user.email) > -1));, получавам грешка на компилатора.   -  person Jake12342134    schedule 06.08.2019
comment
нека първо да разбера --› addUserEmails е масивът с условията на филтъра, което означава, че ако имейлът е там, не искате да показвате потребителя в таблицата. Как се нарича потребителският масив, който искате да филтрирате. Можете ли да публикувате целия компонент.ts   -  person sagat    schedule 06.08.2019
comment
this.users е users: MatTableDataSource<GoogleUser> = new MatTableDataSource([]);, всичко, което искам да направя, е да филтрирам данните, така че ако има имейли в източника на данни в addedUserEmails, те да не се показват в таблицата   -  person Jake12342134    schedule 06.08.2019
comment
добре, направих stackblitz. Отговарям след секунда   -  person sagat    schedule 06.08.2019
comment
Колега, може да се наложи да направите това MatTableDataSource‹GoogleUser[]›, не сте посочили колекция от потребители, а един потребител.   -  person sagat    schedule 06.08.2019


Отговори (2)


Бих го направил така:

applyAddedUserFilter() {
    this._usersService.addedUsers$.subscribe((addedUsers: AddedUser[]) => {
      let addedUserEmails: string[] = addedUsers.map(user => user.email);

      this.dataSource.data = this.users.filter((user: GoogleUser) => !(addedUserEmails.indexOf(user.email) > -1));
    });
  }

Ето един stackblitz: Филтър за таблица с материали

person sagat    schedule 06.08.2019
comment
Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. Това е грешката на компилатора, която получавам, когато се опитвам да използвам този ред код. - person Jake12342134; 06.08.2019
comment
Проверихте ли stackblitz? Можете ли да предоставите вашия код на компонента while? - person sagat; 06.08.2019
comment
Това е така, защото вашият GoogleUser Type и String не са едни и същи типове. - person sagat; 06.08.2019

Това е късен отговор, но със сигурност ще помогне на тези, които се интересуват.

Можете да използвате mat-table-filter за филтриране. Поддържа и филтриране на масиви. Това ви спестява от внедряване на шаблон за филтриране, включително отблъскване и т.н.

Единственото нещо, което трябва да направите, е да добавите директива matTableFilter към вашата таблица с материали и да обвържете exampleEntity с представяне на това, което имате като елемент във вашия източник на данни.

 <table mat-table matTableFilter [dataSource]="dataSource"
 [exampleEntity]="exampleObject"...>

Това е всичко. Когато попълните свойствата на exampleObject, филтърът автоматично ще работи добре с поддръжката за премахване на удари по подразбиране. Можете също да промените времето за премахване на отскок.

Можете да разгледате примерите тук: https://halittalha.github.io/ng-material-extensions/

Споделям пълния изходен код за филтриране на масиви по-долу. Примерът по-долу използва компонент чипове за събиране на съдържанието на масива за филтриране.

.html

<mat-table matTableFilter [exampleEntity]="filterEntity" [filterType]="filterType" [dataSource]="dataSource"
  class="mat-elevation-z8">
  <ng-container matColumnDef="category">
    <mat-header-cell *matHeaderCellDef>
      <mat-form-field appearance="outline">
        <input matInput placeholder="Category" [(ngModel)]="filterEntity.category">
      </mat-form-field>
    </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.category}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="brand">
    <mat-header-cell *matHeaderCellDef>
      <mat-form-field appearance="outline">
        <input matInput placeholder="Product Brand" [(ngModel)]="filterEntity.brand">
      </mat-form-field>
    </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.brand}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="availableSizes">
    <mat-header-cell *matHeaderCellDef>

      <mat-form-field class="example-chip-list">
        <mat-chip-list #chipList aria-label="Fruit selection">
          <mat-chip *ngFor="let size of filterEntity.availableSizes" [selectable]="true" [removable]="true"
            (removed)="remove(size)">
            {{size}}
            <mat-icon matChipRemove>cancel</mat-icon>
          </mat-chip>
          <input placeholder="Add Size" [matChipInputFor]="chipList"
            [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
            (matChipInputTokenEnd)="add($event)">
        </mat-chip-list>
      </mat-form-field>
    </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.availableSizes}} </mat-cell>
  </ng-container>

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

.ts

import { MatTableFilter } from 'mat-table-filter';
import { Component, OnInit } from '@angular/core';
import { MatTableDataSource, MatChipInputEvent } from '@angular/material';
import { COMMA, ENTER } from '@angular/cdk/keycodes';

export class Product {
  category: string;
  brand: string;
  availableSizes: Array<string>;
}

const PRODUCTS: Product[] = [
  {category: 'T-Shirt', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
  {category: 'T-Shirt', brand: 'Y', availableSizes: ['S', 'L', 'XL']},
  {category: 'T-Shirt', brand: 'Z', availableSizes: ['XL']},
  {category: 'Jean', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
  {category: 'Jean', brand: 'Y', availableSizes: ['S', 'M']},
  {category: 'Jean', brand: 'Z', availableSizes: ['S', 'M', 'L']},
  {category: 'Jean', brand: 'B', availableSizes: ['S', 'M', 'L']},
  {category: 'Jacket', brand: 'X', availableSizes: ['S', 'L', 'XL']},
  {category: 'Jacket', brand: 'Z', availableSizes: ['S']},
  {category: 'Pants', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
  {category: 'Pants', brand: 'Y', availableSizes: ['L', 'XL']},
  {category: 'Pants', brand: 'Z', availableSizes: ['S']},
  {category: 'Hat', brand: 'X', availableSizes: ['S', 'M', 'L']},
  {category: 'Skirt', brand: 'X', availableSizes: ['S', 'M', 'L', 'XL']},
  {category: 'Skirt', brand: 'Y', availableSizes: ['S', 'M', 'L']}
 ];

@Component({
  selector: 'app-array-filter',
  templateUrl: './array-filter.component.html',
  styleUrls: ['./array-filter.component.css']
})
export class ArrayFilterComponent implements OnInit {
  filterEntity: Product;
  filterType: MatTableFilter;
  displayedColumns: string[] = ['category', 'brand', 'availableSizes'];
  dataSource;
  readonly separatorKeysCodes: number[] = [ENTER, COMMA];

  add(event: MatChipInputEvent): void {
    const input = event.input;
    const value = event.value;

    if ((value || '').trim()) {
      this.filterEntity.availableSizes.push(value.trim());
    }

    // Reset the input value
    if (input) {
      input.value = '';
    }
  }

  remove(size: string): void {
    const index = this.filterEntity.availableSizes.indexOf(size);

    if (index >= 0) {
      this.filterEntity.availableSizes.splice(index, 1);
    }
  }

  ngOnInit() {
    this.filterEntity = new Product();
    this.filterEntity.availableSizes = new Array<string>(); // DO NOT FORGET TO INIT THE ARRAY
    this.filterType = MatTableFilter.ANYWHERE;
    this.dataSource = new MatTableDataSource(PRODUCTS);
  }
}
person talhature    schedule 04.06.2020