在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()))
这一行给出了错误,即用户和
中未定义toLocaleLowerCaseconsole.log(this.users[filterData.criteria]);
给了我&#39; undefined&#39;。
感谢您的帮助,
最好的问候
答案 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')
);
}
}
感谢您的帮助。
最好的问候。