Angular Material Table拥有过滤方法

时间:2018-02-21 14:26:53

标签: angular rxjs angular-material

tutorial的帮助下,我为角度材质表编写了自己的数据源。我从api获取数据列表并将其显示在材料表中。

代码MyDataSource

export class MyDataSource extends DataSource<any> {

  private users: Observable<User[]>;

  constructor(private userService: UserService) {
    super();
  }

  connect(): Observable<User[]> {
    this.users = this.userService.getAll();
    return this.users;
  }

  disconnect() { }

  filterWithCriteria(filterData: any): any {
    return this.users
      .filter(element => element[filterData.criteria].toLocaleLowerCase().includes(filterData.searchTerm.toLocaleLowerCase()))
      .map(element => element)
      .subscribe(
        element => console.log(element),
        err => console.error(err),
        () => console.log('Streaming is over')
      );
   }
}

api提供了一个带有用户对象的可观察对象。

代码用户

export class User implements models.User {
  constructor(
    public name?: string,
    public adress?: string,
    public email?: string,
    public telefon?: string,
    public birthday?: Date
  ) {}
}

目标是使用条件在用户列表中进行搜索。标准可以是姓名,地址,......

.filter(element => element[filterData.criteria].toLocaleLowerCase().includes(filterData.searchTerm.toLocaleLowerCase()))

这一行给出了错误,即用户和

中未定义toLocaleLowerCase
 console.log(this.users[filterData.criteria]);

给了我&#39; undefined&#39;。

感谢您的帮助,

最好的问候

2 个答案:

答案 0 :(得分:1)

你的例子中有(我认为)两个错误:

1 /似乎你的userService.getAll()将一个Observable返回给一个可以发出一组用户的observable。

所以当你确实返回this.users.filter时(element ...元素是User的数组,而不是User

那么好的过滤链应该是

filterWithCriteria(filterData: any): any {
    return this.users
      .map((users: User[] => {
          return users.filter(user => {
              return user[filterData.criteria].toLocaleLowerCase().includes(filterData.searchTerm.toLocaleLowerCase());
          });  
      })
      .subscribe(
        users => console.log(users),
        err => console.error(err),
        () => console.log('Streaming is over')
      );
   }

2 / DataSource的连接应该是发出要显示的用户的Observable。因此,connect方法需要返回一个Observable,它将在更改过滤器(或更改Users列表)时发出新数据。我们缺乏有关如何实施过滤器的信息,但这是一个实现示例

export class MyDataSource extends DataSource<User[]> {

        private users: Observable<User[]>;
        private filter$ = new BehaviorSubject({criteria: null, searchTerm: null});
        /*
            Every time your filter change you have to call
            this.filter$.next({criteria: <theCriteria>, searchTerm: <theTerm>});
        */

        constructor(private userService: UserService) {
            super();
        }

        connect(): Observable<User[]> {
            return Observable.combineLatest(this.userService.getAll(), this.filter$)
                .map(latestValues => {
                    // every time filter$ or the observable from userService.getAll() emit a new data
                    const [users, filterData] = latestValues;
                    if (!filterData.criteria || !filterData.searchTerm) return users;

                    return users.filter(user => {
                        return user[filterData.criteria].toLocaleLowerCase().includes(filterData.searchTerm.toLocaleLowerCase());
                    });
                });
        }

        disconnect() {}
    }

注意:处理此问题的最佳方法可能是在您的包装组件中使用过滤器$ Subject,并将其传递给DataSource的构造函数。

希望它有所帮助!

答案 1 :(得分:1)

@Pierre Mallet你的过滤器解决方案有效,但我真的不知道在哪里打电话

this.filter$.next({criteria: <theCriteria>, searchTerm: <theTerm>});
由于选择了角度材料,我做了一点改变。

我的实际代码

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';
import 'rxjs/add/observable/combineLatest';
import { DataSource } from '@angular/cdk/collections';
import { UserService } from '../shared/service/user.service';
import { User } from '../shared/user';
import { TransponderFormComponent } from '../transponder-form/transponder-form.component';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Component({
  selector: 'app-transponder-list',
  templateUrl: './transponder-list.component.html',
  styleUrls: ['./transponder-list.component.scss']
})

export class TransponderListComponent implements OnInit {

  public users: User[];
  public displayedColumns = ['name', 'adress', 'city', 'email', 'telephon', 'birthday'];
  public dataSource;
  public selectedCriteria: String = '';

  public searchCriteria = [
    { value: 'name', view: 'Name' },
    { value: 'city', view: 'City' },
    { value: 'adress', view: 'Adress' },
    { value: 'email', view: 'Email' },
    { value: 'telephon', view: 'Telephon' },
    { value: 'birthday', view: 'Birthday' }
  ];

  constructor(private userService: UserService) { }

  ngOnInit() {
    this.dataSource = new MyDataSource(this.userService);
  }

  // get data from material select
  public setSearchCriteria() { }

  public filter(data: any) {
    this.dataSource.filter(data.searchTerm, this.selectedColumn);
  }
}

export class MyDataSource extends DataSource<any> {

  private users: Observable<User[]>;
  private filter$ = new BehaviorSubject({ criteria: null, searchTerm: null });

  constructor(private userService: UserService) {
    super();
  }

  connect(): Observable<User[]> {
    this.users = this.userService.getAll();
    return Observable.combineLatest(this.userService.getAll(), this.filter$)
      .map(latestValues => {
         const [users, filterData] = latestValues; // change
         if (!filterData.criteria || !filterData.searchTerm) {
           return users;
         }
         return users.filter(user => {
           return user[filterData.criteria].toLocaleLowerCase().includes(filterData.searchTerm.toLocaleLowerCase());
         });
       });
  }

  disconnect() { }

  filter(searchTerm: String, criteria: String) {
    if (searchTerm !== '') {
      // there is a tern to search
      if ((criteria !== undefined) && (criteria !== '')) {
        console.log('Search with term and criteria');
        this.filterWithCriteria(searchTerm, criteria);
      }
    }
  }

  filterWithCriteria(searchTerm: String, criteria: any): any {
    return this.users
      .map((users: User[]) => {
        return users.filter(user => {
          return user[criteria].toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase());
        });
      })
      .subscribe(
        users => console.log(users),
        err => console.error(err),
        () => console.log('Streaming is over')
      );
  }
}

感谢您的帮助。

最好的问候。