typescript 在所有列上实现 NGX 数据表过滤
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45106241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Implementing NGX Datatable filtering on all columns
提问by Blankdud
I've been trying to get this working with no luck. I've been referencing these resources for help:
http://swimlane.github.io/ngx-datatable/#filter
https://github.com/swimlane/ngx-datatable/blob/master/demo/basic/filter.component.ts
我一直试图让这个工作没有运气。我一直在参考这些资源寻求帮助:http:
//swimlane.github.io/ngx-datatable/#filter
https://github.com/swimlane/ngx-datatable/blob/master/demo/basic/filter。组件.ts
Basically i just want to allow my filter to apply to more than a single column, without implementing code to handle every column. (Some datatables have 20+ columns!)
基本上我只想让我的过滤器应用于多个列,而不需要实现代码来处理每一列。(一些数据表有 20 多列!)
Example Code:
示例代码:
//HTML
<input type='text' placeholder='Filter' (keyup)='updateFilter($event.target.value)' />
<ngx-datatable
class="material"
columnMode="force"
[columns]="gridProperties.FilteredColumns"
[footerHeight]="50"
[loadingIndicator]="gridLoadingIndicator"
[rows]="filteredList"
[scrollbarH]="false"
[scrollbarV]="true"
[selected]="selectedItem"
[selectionType]="'single'"
style="min-height:400px;">
</ngx-datatable>
//TYPESCRIPT
public items: Item[];
updateFilter(filterValue) {
const lowerValue = filterValue.toLowerCase();
this.filteredList = this.items.filter(item => item.name.toLowerCase().indexOf(lowerValue) !== -1 || !lowerValue);
}
Here I am obviously just handling filtering for the 'name' property of my items array. This works great as is, but like I had mentioned, if the grid contains many columns I'd like one method to handle all of them. Any help or tips are appreciated.
在这里,我显然只是在处理对我的 items 数组的“name”属性的过滤。这很好用,但就像我提到的那样,如果网格包含许多列,我想要一种方法来处理所有这些列。任何帮助或提示表示赞赏。
回答by Cole Paciano
Using the example TS file for filtering (https://github.com/swimlane/ngx-datatable/blob/master/demo/basic/filter.component.ts) as a foundation, I was able to successfully make it filter all columns dynamically (it will filter all columns without the need to specify them). I've included what I believe to be all the necessary parts for this to work but also trimmed the code down as much as I could to make it easier to understand.
使用示例 TS 文件进行过滤(https://github.com/swimlane/ngx-datatable/blob/master/demo/basic/filter.component.ts)作为基础,我能够成功地使其过滤所有列动态(它将过滤所有列而无需指定它们)。我已经包含了我认为是使其工作的所有必要部分,但也尽可能地减少了代码以使其更容易理解。
HTML
HTML
<ngx-datatable
#table
class="material striped scroll-vertical"
[rows]="data"
[columns]="cols"
[columnMode]="'force'"
[headerHeight]="35"
[footerHeight]="35"
[rowHeight]="'auto'"
[limit]="pageSize"
[selectionType]="'single'">
<input type="text" (keyup)='filterDatatable($event)'>
TYPESCRIPT
打字稿
cols = [{name:'First Name'},{name:'Last Name'},{name:'Address'}];
data = [];
filteredData = [];
// dummy data for datatable rows
dummyData = [
{firstName:'Daenarys',lastName:'Targaryen',address:'Dragonstone'},
{firstName:'Sansa',lastName:'Stark',address:'Winterfell'},
{firstName:'Cersei',lastName:'Lannister',address:'Kings Landing'},
{firstName:'Brienne',lastName:'Tarth',address:'Sapphire Island'},
{firstName:'Lyanna',lastName:'Mormont',address:'Bear Island'},
{firstName:'Margaery',lastName:'Tyrell',address:'Highgarden'}
]
ngOnInit(){
// populate datatable rows
this.data = this.dummyData;
// copy over dataset to empty object
this.filteredData = this.dummyData;
}
// filters results
filterDatatable(event){
// get the value of the key pressed and make it lowercase
let val = event.target.value.toLowerCase();
// get the amount of columns in the table
let colsAmt = this.cols.length;
// get the key names of each column in the dataset
let keys = Object.keys(this.dummyData[0]);
// assign filtered matches to the active datatable
this.data = this.filteredData.filter(function(item){
// iterate through each row's column data
for (let i=0; i<colsAmt; i++){
// check for a match
if (item[keys[i]].toString().toLowerCase().indexOf(val) !== -1 || !val){
// found match, return true to add to result set
return true;
}
}
});
// whenever the filter changes, always go back to the first page
this.table.offset = 0;
}
回答by Josu
here is an example of your code with multiple columns filtering:
这是具有多列过滤的代码示例:
updateFilter(filter: string): void {
const val = filter.trim().toLowerCase();
this.filteredList = this.items.slice().filter((item: any) => {
let searchStr = '';
for (let i = 0; i < this.gridProperties.FilteredColumns.length; i++) {
searchStr += (item[this.gridProperties.FilteredColumns[i]]).toString().toLowerCase();
}
return searchStr.indexOf(val) !== -1 || !val;
});
}
If I did not made any errors, it should work correctly.
如果我没有犯任何错误,它应该可以正常工作。
回答by Mauricio Gracia Gutierrez
This answer improves an existing answer by Cole Paciano :
这个答案改进了 Cole Paciano 的现有答案:
- Column names to be searched are only created once and not whenever a key is pressed
- Cell with
null
values are correctly handled (no console errors) - Full rows are shown (because filter is applied to row array)
- Column names to be searched can also be specified by hand to only include some of them (exclude guids, ids, etc)
- 要搜索的列名仅创建一次,而不是每次按下键时创建
null
正确处理带有值的单元格(没有控制台错误)- 显示完整行(因为过滤器应用于行数组)
- 要搜索的列名也可以手动指定以仅包含其中的一些(排除 guids、ids 等)
Here are the steps:
以下是步骤:
In the template
(html) file add an input with a keyup
handler
在template
(html) 文件中添加一个带有keyup
处理程序的输入
Search:
<input type="text" (keyup)='filterDatatable($event)'>
<ngx-datatable
class="material"
[rows]="rows"
[columns]="columns"
headerHeight="35"
rowHeight ="35">
</ngx-datatable>
In the component
add the following filteredData
and columnsWithSearch
在component
添加以下内容filteredData
和columnsWithSearch
export class ListParkingsComponent implements OnInit {
columns = [];
rows = [];
filteredData = [];
columnsWithSearch : string[] = [];
ngOnInit() {
this.rows = getData() ; //recover data from API/database/datasource
this.filteredData = this.rows;
// for specific columns to be search instead of all you can list them by name
this.columnsWithSearch = Object.keys(this.rows[0]);
}
getData() {
//your current logic to fill the rows of the table
}
// filters results
filterDatatable(event){
// get the value of the key pressed and make it lowercase
let filter = event.target.value.toLowerCase();
// assign filtered matches to the active datatable
this.rows = this.filteredData.filter(item => {
// iterate through each row's column data
for (let i = 0; i < this.columnsWithSearch.length; i++){
var colValue = item[this.columnsWithSearch[i]] ;
// if no filter OR colvalue is NOT null AND contains the given filter
if (!filter || (!!colValue && colValue.toString().toLowerCase().indexOf(filter) !== -1)) {
// found match, return true to add to result set
return true;
}
}
});
// TODO - whenever the filter changes, always go back to the first page
//this.table.offset = 0;
}
回答by Siddhartha Mukherjee
You might be helped
你可能会得到帮助
<input
type="text"
style="padding:8px;margin:15px auto;width:30%;"
placeholder="Type to filter the name column..."
(keyup)="updateFilter($event)"
/>
<ngx-datatable
#table
class="material"
[columns]="columns"
[columnMode]="ColumnMode.force"
[headerHeight]="50"
[footerHeight]="50"
rowHeight="auto"
[limit]="10"
[rows]="rows"
>
</ngx-datatable>
updateFilter(event) {
const val = event.target.value.toLowerCase();
// filter our data
const temp = this.temp.filter(function(d) {
return d.name.toLowerCase().indexOf(val) !== -1 ||
d.address.toLowerCase().indexOf(val) !== -1 ||
d.gender.toLowerCase().indexOf(val) !== -1 || !val;
});
// update the rows
this.rows = temp;
// Whenever the filter changes, always go back to the first page
this.table.offset = 0;
}
https://github.com/swimlane/ngx-datatable/blob/master/src/app/basic/dark-theme.component.ts
https://github.com/swimlane/ngx-datatable/blob/master/src/app/basic/dark-theme.component.ts
回答by Abhilasha
While storing the data in rows list at that time also initilize perttemp list, so that we can fetch after filter
此时在将数据存储在行列表中的同时还要初始化 perttemp 列表,以便我们可以在过滤后获取
updateFilter(event) {
const val = event.target.value.toLowerCase();
if(val) {
this.temp = this.rows;
// filter our data
const temp = this.temp.filter(function (d) {
return ( d.name.toLowerCase().indexOf(val) !== -1 || d.email.toLowerCase().indexOf(val) !== -1 || !val);
});
this.rows = temp;
}
else
{
this.rows = this.perttemp;
}
}
回答by Judson Terrell
There were a few issues when using some of the above answers to i am adding my own...
使用上述一些答案时出现了一些问题,我正在添加我自己的...
First its best to store the keys in a global variable, because things get overwritten on each iteration.
首先最好将键存储在一个全局变量中,因为每次迭代时都会被覆盖。
problems solved...
问题解决了...
if data is pushed via an input we need to reset the keys especially if there was no data to begin with.
Store everything in a temp variable to always retain original data.**
如果数据是通过输入推送的,我们需要重置键,尤其是在没有数据开始的情况下。
将所有内容存储在临时变量中以始终保留原始数据。**
I am posting my entire usage here..
我在这里发布了我的全部用法..
import {
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild,
} from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'verasci-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.scss'],
})
export class DataTableComponent implements OnInit, OnChanges {
@ViewChild('table') table;
@Input() rows;
@Input() columns;
@Input() searchBar;
keys;
temp: Array<any>;
@Output() selectEvent$ = new EventEmitter();
selected = [];
readonly pageLimit = 10;
readonly headerHeight = 50;
readonly rowHeight = 50;
constructor(private readonly el: ElementRef, private readonly router: Router) { }
async ngOnInit() {
this.temp = this.rows;
this.keys = this.rows[0] ? Object.keys(this.rows[0]) : null;
setTimeout(() => { this.dataLoaded = true; }, 200);
}
// we need to reset keys and temp data if data is pushed to the table.
ngOnChanges(changes: SimpleChanges) {
this.keys = this.rows[0] ? Object.keys(this.rows[0]) : null;
this.temp = this.rows;
}
filterSingle(event) {
const val = event.target.value.toLowerCase();
// filter our data
const temp = this.temp.filter((d) => {
return d.sponsor.toLowerCase().indexOf(val) !== -1 || !val;
});
// update the rows
this.rows = temp;
// Whenever the filter changes, always go back to the first page
this.table.offset = 0;
}
filterMulti(event) {
// get the value of the key pressed and make it lowercase
const val = event.target.value.toLowerCase();
// get the amount of columns in the table
const colsAmt = this.columns.length;
// get the key names of each column in the dataset
const keys = this.keys; // just need to keys from the first set of rw
// filter our data
const temp = this.temp.filter(item => {
// iterate through each row's column data
for (let i = 0; i < colsAmt; i++) {
// check for a match on properties that are not null
if (item[keys[i]] != null && (item[keys[i]].toString().toLowerCase().indexOf(val) !== -1 || !val)) {
// found match, return true to add to result set
return true;
}
}
});
// update the rows
this.rows = temp;
// Whenever the filter changes, always go back to the first page
this.table.offset = 0;
}
onSelect({ selected }) {
this.selectEvent$.emit({ selected: selected[0] });
}
}
回答by Sachin from Pune
import { DatatableComponent } from '@swimlane/ngx-datatable';
ViewChild(DatatableComponent) table: DatatableComponent;
updateFilter(event) {
const val = event.target.value.toLowerCase();
var returnData: any;
// filter our data
const temp = this.temp.filter(function (d) {
if (d.yourFirstColumnName.toLowerCase().indexOf(val) !== -1 || !val) {
returnData = d.user_name.toLowerCase().indexOf(val) !== -1 || !val;
} else if (d.yourSecondColumnName.toLowerCase().indexOf(val) !== -1 || !val) {
returnData = d.notes_title.toLowerCase().indexOf(val) !== -1 || !val;
}
return returnData;
});
<input placeholder="Search Order" (keyup)='updateFilter($event)'>
回答by Abhijit Hole
updateFilter(event) {
const val = event.target.value.toLowerCase();
const temp = this.temp.filter(index => {
return (index.name.toLowerCase().indexOf(val) !== -1 ||
index.company.toLowerCase().indexOf(val) !== -1 ||
index.gender.toLowerCase().indexOf(val) !== -1 ||
!val);
});
this.company = temp;
this.table.offset = 0;
}