我正在尝试仅使用一个Array
基于多个列过滤Pipe
个数据。现在,它过滤第一列值。请检查下面的代码并帮我解决这个问题。
我的代码:
@Pipe({ name: "dataFilter", pure: false })
export class DataFilterPipe implements PipeTransform {
transform(value: Array<any>, filter: any[]) {
if (!filter) {
return value;
} else if (value) {
return value.filter(item => {
for (var i = 0; i < filter.length; i++) {
if (filter[i][1] == undefined) {
return true;
} else if ((typeof item[filter[i][0]] === 'string' || item[filter[i][0]] instanceof String) &&
(item[filter[i][0]].toLowerCase().indexOf(filter[i][1]) !== -1)) {
return true;
}
return false;
}
});
}
}
}
我正在传递dataFilter : [['column1',value1],['column2',value2],['column3',value3]]
等数据。
答案 0 :(得分:23)
这是使用作为多列过滤器传递的对象的解决方案。我发现它传递2D数组更方便:
@Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: Array<any>, filter: {[key: string]: any }): Array<any> {
return items.filter(item => {
let notMatchingField = Object.keys(filter)
.find(key => item[key] !== filter[key]);
return !notMatchingField; // true if matches all fields
});
}
}
拥有包含多列的对象数组:
this.people = [
{name: 'John', age: 27, sex: 'male'},
{name: 'Lara', age: 21, sex: 'female'},
{name: 'Rick', age: 29, sex: 'male'},
{name: 'Eva', age: 27, sex: 'female'},
{name: 'Mike', age: 27, sex: 'male'}
];
过滤器:
this.peopleFilter = {age: 27, sex: 'male'};
使用它像:
<div *ngFor="let person of people | filter: peopleFilter;"></div>
因此,有两个人符合我们的标准: John 和 Mike 。
答案 1 :(得分:2)
替换您的代码,如下所示,
export class DataFilterPipe implements PipeTransform {
transform(value: Item[], field: string, args: string): Item[]{
let filter: string = args ? args.toLocaleLowerCase() : null;
return filter ? value.filter((item : Item) =>
Item[field].toLocaleLowerCase().indexOf(filter) != -1) : value;
}
}
在Html页面中,
<tbody *ngFor="let item of items | dataFilter : columnName : value ">
答案 2 :(得分:1)
我假设您有一个包含这样的列的数组:
[{col1:"col1",col2:"col2",col3:"col3"}]
我也省略了所有类型签入,空指针和错误处理。当前的解决方案是我尝试使用数组的一个例子:
myData:Array<any> = [{col1:"a",col2:"b",col3:"cadd"},
{col1:"abba",col2:"bobba",col3:"cadd"},
{col1:"abba",col2:"bobba",col3:"cool"},
{col1:"a",col2:"bobba",col3:"cool"}];
和管道:
@Pipe({
name: 'dataFilter'
})
export class DataFilterPipe implements PipeTransform {
transform(value: any, args?: any): any {
return value.filter(item =>{
var matchesAll = true;
for(var i = 0; i<args.length; i++){
// check if your data contains the column and the value defined in args.
if(item.hasOwnProperty(args[i][0]) && item[args[i][0]]==args[i][1]){
continue;
}else{ // at least one column did not match,
matchesAll = false;
}
}
return matchesAll;
});
}
}
然后你可以打电话
dataFilter.transform(myData,[["col1","abba"],["col2","bobba"],["col3","cool"]]);
为了获得一个结果,即转换后的第3行:[{col1:"abba",col2:"bobba",col3:"cool"}]
。
注意:您可能需要调整示例中列的名称,以使其与您的代码一起使用。
编辑:使用此解决方案,您还可以传递任意数量的列。
例如dataFilter.transform(myData,[["col3","cool"]]);
将导致转换后的最后两行(来自我的示例):
[{col1:"abba",col2:"bobba",col3:"cool"},{col1:"a",col2:"bobba",col3:"cool"}]
编辑:在评论说明代码无法正常工作后,我提供了上述示例的一个内容:https://plnkr.co/edit/VdpGJWyzWUVFzYNDSz1g
答案 3 :(得分:1)
这是我对Angular 8所做的事情:
目标:从给定关键字的项目列表中搜索多个属性,例如“ Property1”和“ Property2”:
app.module.ts:
......
import { MyFilterPipe } from './shared/pipes/my-filter.pipe';
@NgModule({
declarations: [
...
MyFilterPipe
],
imports: [
...
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
管道:content-filter.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'myFilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items: any[], keyword: any, properties: string[]): any[] {
if (!items) return [];
if (!keyword) return items;
debugger;
return items.filter(item => {
var itemFound: Boolean;
for (let i = 0; i < properties.length; i++) {
if (item[properties[i]].toLowerCase().indexOf(keyword.toLowerCase()) !== -1) {
itemFound = true;
break;
}
}
return itemFound;
});
}
}
组件:
<input type="search" class="form-control filter-list-input" placeholder="Filter"
aria-label="Filter" name="search" [(ngModel)]="searchText" >
<div *ngFor="let itemof myItems | myFilter:searchText:['Property1', 'Property2']; let i = index">...
</div>
component.ts:
export class MyListComponent implements OnInit {
...
searchText: string;
答案 4 :(得分:0)
您可以看到整个工作 ArrayFilterPipe.ts @ http://typescript.io/uN29xRdF1Ag或typescriptlang.org 下面我还附上了打字稿的编译JS,以便于查看所需的输出。 如果想要代码注释,请告诉我......
在执行过滤器之前,FYI选项数组被转换为对象,因为它对数组感觉很舒服。
/* yours */
var option = [['column1',value1],['column2',value2],['column3',value3]];
/* mine */
var option = { column1: 'value1', column2: 'value2', column3: 'value3' };
static _arrayToObject(value: Array<Array<any>>): any {
return (ArrayFilterPipe._isUndefined(value) || value == null)
? value
: value.reduce((result, current) => {
result[current[0]] = current[1];
return result;
} , {});
}
您还可以通过https://github.com/angular/angular.js/blob/master/src/ng/filter/filter.js
获取灵感来构建类似于角度1.x的数组/对象过滤器
var ArrayFilterPipe = (function () {
function ArrayFilterPipe() {
}
ArrayFilterPipe._isOfType = function (value, type) {
return typeof (value) === type;
};
ArrayFilterPipe._isUndefined = function (value) {
return ArrayFilterPipe._isOfType(value, ArrayFilterPipe.TYPES.UNDEFINED);
};
ArrayFilterPipe._isObject = function (value) {
return ArrayFilterPipe._isOfType(value, ArrayFilterPipe.TYPES.OBJECT);
};
ArrayFilterPipe._isOrHasMatch = function (value, target) {
return ArrayFilterPipe._isOfType(value, ArrayFilterPipe.TYPES.STRING) || ArrayFilterPipe._isOfType(target, ArrayFilterPipe.TYPES.STRING)
? value.toString().toLowerCase().indexOf(target.toString().toLowerCase()) >= 0
: value == target;
};
ArrayFilterPipe._hasOptions = function (value, options) {
return (ArrayFilterPipe._isUndefined(value) || ArrayFilterPipe._isUndefined(options) ? (ArrayFilterPipe._isUndefined(value) && ArrayFilterPipe._isUndefined(options))
: (value === null || options == null) ? (value === null && options == null)
: (Array.isArray(value) || Array.isArray(options)) ? false
: ArrayFilterPipe._isObject(value) ?
(ArrayFilterPipe._isObject(options)
? Object.keys(options).every(function (key) { return value.hasOwnProperty(key) && ArrayFilterPipe._isOrHasMatch(value[key], options[key]); })
: Object.values(value).some(function (val) { return ArrayFilterPipe._isOrHasMatch(val, options); }))
: !ArrayFilterPipe._isObject(value) ?
(!ArrayFilterPipe._isObject(options)
? ArrayFilterPipe._isOrHasMatch(value, options)
: false)
: false);
};
ArrayFilterPipe._arrayToObject = function (value) {
return (ArrayFilterPipe._isUndefined(value) || value == null) ? value : value.reduce(function (result, current) {
result[current[0]] = current[1];
return result;
}, {});
};
ArrayFilterPipe.prototype.transform = function (value, options) {
if (!value || !Array.isArray(value) || ArrayFilterPipe._isUndefined(options) || options === null) {
return value;
}
options = Array.isArray(options) ? ArrayFilterPipe._arrayToObject(options) : options;
return value.filter(function (item) { return ArrayFilterPipe._hasOptions(item, options); });
};
return ArrayFilterPipe;
}());
ArrayFilterPipe.TYPES = {
OBJECT: 'object',
STRING: 'string',
UNDEFINED: 'undefined'
};
/*
TESTING
--------------------------------------------------
*/
var pipe = new ArrayFilterPipe();
var array = [null, undefined, , true, 123123, 'Jeke HeNry', 'joe', 'joe hen', {}, [], { fake: 'hen' }, { name: 'hen' }, { name: 'johenrik', country: 'hen' }, { name: 'joe dick', city: 'hen' }, { name: 'Jeke HeNry', country: 'zxy' }];
var options = null;
/* REF: http://stackoverflow.com/questions/11403107/capturing-javascript-console-log */
var oldLog = console.log;
console.log = function (message) {
var _arguments = arguments;
var div = Object.keys(arguments).map(function (key) { return Number(key); }).reduce(function (result, key) {
result = result || document.createElement('div');
var isJSON = (_arguments[key] != null && (typeof (_arguments[key]) === 'object' || Array.isArray(_arguments[key])));
var span = document.createElement(isJSON ? 'pre' : 'span');
span.innerHTML = isJSON ? JSON.stringify(_arguments[key], undefined) : _arguments[key].replace('\n', '</br></br>');
result.appendChild(span);
return result;
}, null);
document.body.appendChild(div);
oldLog.apply(console, arguments);
};
function test() {
console.log('options', options);
console.log('result', pipe.transform(array, options));
}
console.log('case : 01');
console.log('---------------------------------------------------');
options = 'hen';
test();
console.log('\ncase : 02');
console.log('---------------------------------------------------');
options = { name: 'hen' };
test();
options = [['name', 'hen']];
test();
console.log('\ncase : 03');
console.log('---------------------------------------------------');
options = { name: 'hen', country: 'hen' };
test();
options = [['name', 'hen'], ['country', 'hen']];
test();
console.log('\ncase : 04');
console.log('---------------------------------------------------');
options = { name: 'hen', city: 'hen', fake: true };
test();
options = [['name', 'hen'], ['country', 'hen'], ['fake', true]];
test();
&#13;
答案 5 :(得分:0)
HTML标记:
transform(items: any, filter: any, isAnd: bool): any {
if (filter && Array.isArray(items)) {
let filterKeys = Object.keys(filter);
if (isAnd) {
return items.filter(item =>
filterKeys.reduce((memo, keyName) =>
(memo && new RegExp(filter[keyName], 'gi').test(item[keyName])) || filter[keyName] === "", true));
} else {
return items.filter(item => {
return filterKeys.some((keyName) => {
console.log(keyName);
return new RegExp(filter[keyName], 'gi').test(item[keyName]) || filter[keyName] === "";
});
});
}
} else {
return items;
}
}
转换功能:
timeZone
参考:https://long2know.com/2017/04/angular-pipes-filtering-on-multiple-keys/
答案 6 :(得分:0)
我必须拥有一个Pipe,它可以通过特定的属性值和称为“ All”的通用值进行过滤。用户可以通过从下拉列表中选择它们来动态调整这些过滤器(从而使用效率较低的foreach()
配置)。
在组件中(默认为“全部”)
pure: false
在模板中
public filters = { status: "All", condition: "All", other: "All" };
<div *ngFor="let item of items | filter:filters">