Hi,
I'd like to implement custom filtering based on rows of child grid.
The attached image shows the layout of my grid.
My questions are as follows:
Q1. How to filter the 'company' rows based on the 'customers' who sold more than 100 items?
For eg: After I click 'Customers Selling > 100 Items 4 months' button, I only should show 'Company1' row with 'Customer12' row in its child grid.
Q2. If I want to clear the filter, I should be able to do so as well. (How do I do that in a button? Maybe show active button when used? I'd like your opinion on that.)
Q3. To fetch these data, the server needs to do some expensive calculations, so how can I reuse the dataSource when the customer navigates through different pages instead of doing full fetch from controller while navigating to different pages?
My code looks like this:
The data models:
public
class
CompanyData
{
public
string
CompanyId {
get
;
set
; }
public
int
CustomersCount {
get
;
set
; }
public
List<CompanyCustomer> Customers {
get
;
set
; }
}
public
class
CompanyCustomer
{
public
string
CustomerId {
get
;
set
; }
public
string
CustomerName {
get
;
set
; }
public
int
TotalSoldItems {
get
;
set
; }
}
The grid containing the child grid as well:
@(Html.Kendo()
.Grid<ProjectName.Models.CompanyData>()
.Name(
"CompanyDataSummary"
)
.Columns(columns =>
{
columns.Bound(e => e.CompanyId).Title(
"Company Name"
).Width(60);
columns.Bound(e => e.CustomersCount).Title(
"Customers Count"
).Width(50);
})
.Sortable()
.Pageable()
.Scrollable()
.Filterable()
.ClientDetailTemplateId(
"CustomerDetails"
)
.HtmlAttributes(
new
{ style =
"height:450px;"
})
.AutoBind(
false
)
// Don't load the data yet because I'll need to supply parameters for the fetch
.ToolBar(toolbar => toolbar.ClientTemplateId(
"CustomerDetailsToolBarTemplate"
))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(
true
)
.PageSize(10)
.Model(model =>
{
model.Id(
"CompanyId"
);
model.Field(
"CustomerCount"
,
typeof
(
int
));
})
.Read(read => read.Action(
"GetCompanyDataAsync"
,
"Reporting"
).Data(
"passArguments"
))
)
.Events(events => events.DataBound(
"dataBound"
).DetailExpand(
"onExpand"
))
)
<script id=
"CustomerDetails"
type=
"text/kendo-tmpl"
>
@(Html.Kendo()
.Grid<ProjectName.Models.CompanyCustomer>()
.Name(
"CustomerDetails_#=CompanyId#"
)
.Columns(columns =>
{
columns.Bound(o => o.CustomerName).Title(
"Customer Id"
).Width(60);
columns.Bound(o => o.TotalSoldItems).Title(
"Total Sold Items"
).Width(60);
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Model(model =>
{
model.Id(
"CustomerId"
);
model.Field(
"CustomerName"
,
typeof
(
string
));
model.Field(
"TotalSoldItems"
,
typeof
(
int
));
})
.ServerOperation(
false
)
)
.AutoBind(
false
)
.Pageable()
.Sortable()
.ToClientTemplate()
)
</script>
The toolbar template:
<script id=
"CustomerDetailsToolBarTemplate"
type=
"text/kendo-tmpl"
>
<div
class
=
"inlineBtn"
>
@(Html.Kendo().Button()
.Name(
"allYTDCustomers"
)
.HtmlAttributes(
new
{ type =
"button"
, @
class
=
"k-button"
})
.Content(
"All Customers YTD"
)
.Events(e => e.Click(
"allYTDCustomersFetch"
))
.ToClientTemplate()
)
</div>
<div
class
=
"inlineBtn"
>
@(Html.Kendo().Button()
.Name(
"CustomersGT100ItemsYTD"
)
.HtmlAttributes(
new
{ type =
"button"
, @
class
=
"k-button"
})
.Content(
"Customer selling > 100 items YTD"
)
.Events(e=>e.Click(
"CustomersGT100ItemsYTDFetch"
))
.ToClientTemplate()
)
</div>
<div
class
=
"inlineBtn"
>
@(Html.Kendo().Button()
.Name(
"allCustomersLast4Mths"
)
.HtmlAttributes(
new
{ type =
"button"
, @
class
=
"k-button"
})
.Content(
"Customers selling > 100 items last 4 months"
)
.Events(e => e.Click(
"allCustomersLast4MthsFetch"
))
.ToClientTemplate()
)
</div>
</script>
The script that loads the child grid and the handler for toolbar button:
<script>
function
onExpand(e) {
var
companyId = e.sender.dataItem(e.masterRow).CompanyId;
var
customerData = e.sender.dataItem(e.masterRow).Customers;
//Initialize the child grid as well
var
childGridName =
"#"
+
"CustomerDetails_"
+ companyId;
var
childGrid = $(childGridName).data(
"kendoGrid"
);
if
(childGrid !== undefined) {
childGrid.dataSource.data(customerData);
}
}
//Example
function
:
function
CustomersGT100ItemsYTDFetch() {
// How to filter the company rows based on the customers who sold more than 100 items?
// For eg: After I click that button, I only should show Company1 row with Customer12 in its child grid.
}
</script>
The controller action method:
public
async Task<ActionResult> GetCompanyDataAsync([DataSourceRequest] DataSourceRequest request, DateTime start, DateTime end)
{
IEnumerable<CompanyData> companySummary = await _reporting.GetCompanyReportInformationAsync(start, end);
return
Json(companySummary.ToDataSourceResult(request));
}