角度材料数据表 - 如何为具有提前类型/自动完成搜索的列设置 filterPredicate?
Posted
技术标签:
【中文标题】角度材料数据表 - 如何为具有提前类型/自动完成搜索的列设置 filterPredicate?【英文标题】:Angular Material Data Table - How To Setup filterPredicate For A Column With Type Ahead / Auto Complete Search? 【发布时间】:2019-12-03 04:05:03 【问题描述】:我已经阅读了 SO、Github 等上 filterPredicate 的各种实现,但它们对我理解如何处理预输入搜索没有帮助。
我在输入表单字段中输入了一个字母,比如p
,然后我从数据库中收到了姓氏以p
开头的所有数据。我设置的那部分工作正常。但是,当我输入下一个字母时,我不想再次点击数据库,比如r
。我想过滤以pr
开头的姓氏的数据表。这就是麻烦的开始。
当我键入第二个字母时,我有一个 if/else 语句来测试我正在使用的 var 在字符串中是否有 >1。当它发生时,我将参数传递给一个函数,用于在表上使用已经从数据库下载的数据进行自定义过滤。我避免对每个字母进行 db 调用,这确实有效。我不明白“(数据,过滤器)”。它们看起来像参数,但不是。它们是如何工作的?完成这个需要什么代码?
(我有 `dataSource.filter = filterValue; 在其他地方工作正常。)
参数解释:
column = user_name
filterValue = pr...
困惑:
public filterColumn(column: string, filterValue: string, dataSource)
dataSource.filterPredicate = (data, filter) =>
console.log('data in filter column: ', data); // Never called.
// What goes here?
// return ???;
我的数据源对象。我看到了可以使用的 filterPredicate、data 和 filter 属性。而是抽象如何使用它们。
dataSource in filterColumn: MatTableDataSource _renderData: BehaviorSubject, _filter: BehaviorSubject, _internalPageChanges: Subject, _renderChangesSubscription: Subscriber, sortingDataAccessor: ƒ, …
filterPredicate: (data, filter) => …arguments: [Exception: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
at Function.invokeGetter (<anonymous>:2:14)]caller: (...)length: 2name: ""__proto__: ƒ ()[[FunctionLocation]]: data-utilities.service.ts:43[[Scopes]]: Scopes[3]
filteredData: (3) […, …, …]
sortData: (data, sort) => …
sortingDataAccessor: (data, sortHeaderId) => …
_data: BehaviorSubject _isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …
_filter: BehaviorSubject _isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …
_internalPageChanges: Subject _isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …
_paginator: MatPaginator _isInitialized: true, _pendingSubscribers: null, initialized: Observable, _disabled: false, _intl: MatPaginatorIntl, …
_renderChangesSubscription: Subscriber closed: false, _parentOrParents: null, _subscriptions: Array(1), syncErrorValue: null, syncErrorThrown: false, …
_renderData: BehaviorSubject _isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …data: (...)filter: (...)paginator: (...)sort: (...)__proto__: DataSource
【问题讨论】:
【参考方案1】:我已经包含了我在 Angular 中制作的大部分组件,用于预输入搜索。预输入代码的内容位于底部的实用程序共享组件中。我在这里使用了一个共享组件,因为我会在很多地方使用它。但是,我认为这是一个 hack,并且可能有一个更优雅的答案。这很有效,很容易,但不是那么漂亮。我现在不能花更多的时间来弄清楚漂亮。我怀疑答案在 RegEx 中。
在 .pipe 的 typeahead.compoent 中,您会发现我如何调用实用程序中的代码。
此代码在共享组件 typeahead.component.ts 中
public searchLastName$ = new Subject<string>(); // Binds to the html text box element.
ngAfterViewInit()
// -------- For Column Incremental Queries --------- //
// searchLastName$ binds to the html element.
this.searchLastName$.subscribe(result =>
this.queryLastName(result);
);
// --------- LAST NAME INCREMENTAL QUERY --------------- //
private queryLastName(filterValue)
// Custom filter for this function. If in ngOnInit on the calling component then it applies
// to the whole calling component. We need various filters so that doesn't work.
this.membersComponent.dataSource.filterPredicate = (data: last_name: string , filterValue: string) =>
data.last_name.trim().toLowerCase().indexOf(filterValue) !== -1;
// When the first letter is typed then get data from db. After that just filter the table.
if (filterValue.length === 1)
filterValue = filterValue.trim(); // Remove whitespace
// filterValue = filterValue.toUpperCase(); // MatTableDataSource defaults to lowercase matches
const lastNameSearch = gql`
query ($last_name: String!)
lastNameSearch(last_name: $last_name)
...membersTableFrag
$membersTableFrag
`;
this.apollo
.watchQuery(
query: lastNameSearch,
variables:
last_name: filterValue,
,
)
.valueChanges
.pipe(
map(returnedArray =>
// console.log('returnedArray in map: ', returnedArray); // All last_name's with the letter in them someplace.
const membersArray = returnedArray.data['lastNameSearch']; // extract items array from GraphQL JSON array
// For case insensitive search
const newArray = membersArray.filter(this.utilitiesService.filterBy(filterValue, 'last_name'));
return newArray;
)
)
.subscribe(result =>
this.membersComponent.dataSource.data = result;
);
else
// Filter the table instead of calling the db for each letter entered.
// Note: Apollo client doesn't seem able to query the cache with this kind of search.
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
// Interface and redefinition of filterPredicate in the ngOnInit
this.membersComponent.dataSource.filter = filterValue; // Filters all columns unless modifed by filterPredicate.
utilities.service.ts
// -------------- DATABASE COLUMN SEARCH -------------
// Shared with other components with tables.
// For case insensitive search.
// THIS NEEDS TO BE CLEANED UP BUT I'M MOVING ON, MAYBE LATER
public filterBy = (filterValue, column) =>
return (item) =>
const charTest = item[column].charAt(0);
if (charTest === filterValue.toLowerCase())
return true;
else if (charTest === filterValue.toUpperCase())
return true;
else
return false;
;
【讨论】:
以上是关于角度材料数据表 - 如何为具有提前类型/自动完成搜索的列设置 filterPredicate?的主要内容,如果未能解决你的问题,请参考以下文章