I want to filter my grids having both menu and row filter option. As it is a common scenario, some columns represent a "text-value" field; for example, the category column in Products grid. For this type of columns, I would like to have a "Kendo UI Multi Select" in the menu (which filters based on the value of category), and a simple string filter in the filter row (which basically applies string filtering on the name of category). I wrote the following code to accomplish this, but apparently the grid is got confused to filter based on category' value or category's name.
Here is the template:
<
kendo-grid
[data]="gridData"
[pageSize]="state.take"
[skip]="state.skip"
[sort]="state.sort"
[filter]="state.filter"
filterable
=
"menu, row"
[sortable]="true"
[pageable]="true"
(dataStateChange)="dataStateChange($event)"
[height]="400">
<
kendo-grid-column
field
=
"ProductName"
title
=
"Product Name"
>
</
kendo-grid-column
>
<
kendo-grid-column
field
=
"Category.CategoryName"
title
=
"Category"
>
<
ng-template
kendoGridFilterMenuTemplate
let-column
=
"column"
let-filter
=
"filter"
let-filterService
=
"filterService"
>
<
kendo-multiselect
[data]="categories"
textField
=
"CategoryName"
valueField
=
"CategoryID"
[valuePrimitive]="true"
[value]="categoryFilters(filter)"
(valueChange)="categoryChange($event, filterService)">
</
kendo-multiselect
>
</
ng-template
>
<
ng-template
kendoGridCellTemplate let-dataItem>
{{dataItem.Category?.CategoryName}}
</
ng-template
>
</
kendo-grid-column
>
</
kendo-grid
>
and here is part of the .ts file:
01.
public
filterChange
(filter: CompositeFilterDescriptor):
void
{
02.
this
.state
.filter
= filter;
03.
}
04.
05.
public
categoryChange
(values: any[],
filterService
: FilterService):
void
{
06.
filterService
.filter
({
07.
filters
: values
.map
(value => ({
08.
field
:
'Category.CategoryID'
,
09.
operator
:
'eq'
,
10.
value
11.
})),
12.
logic
:
'or'
13.
});
14.
}
15.
16.
public
categoryFilters
(filter: CompositeFilterDescriptor): FilterDescriptor[] {
17.
return
flatten
(filter)
.map
(({ value }) => value);
18.
}
19.
20.
public
dataStateChange
(state: DataStateChangeEvent):
void
{
21.
this
.state
= state;
22.
this
.gridData
=
process
(sampleProducts,
this
.state
);
23.
}
24.
25.
26.
public
state
: State = {
27.
skip
:
0
,
28.
take
:
6
,
29.
};
30.
31.
public
categories
: any[] =
distinct
(sampleProducts);
32.
public
gridData
: GridDataResult =
process
(sampleProducts,
this
.state
);
33.
34.
35.
const
flatten = filter => {
36.
const
filters = (filter || {})
.filters
;
37.
if
(filters) {
38.
return
filters
.reduce
((acc, curr) => acc
.concat
(curr
.filters
?
flatten
(curr) : [curr]), []);
39.
}
40.
return
[];
41.
};
42.
43.
const
distinct = data => data
44.
.map
(x => x
.Category
)
45.
.filter
((x, idx, xs) => xs
.findIndex
(y => y
.CategoryName
=== x
.CategoryName
) === idx);