Hi,
I have tried the "work around" for creating a separate datasource on a filterable column in a grid but I'm getting an HTTP 500 response when I execute it. My controller code is executed but all I see when the filter dialog box opens is a spinning wheel...
Here is the link to the "work around": https://docs.telerik.com/kendo-ui/knowledge-base/sort-multi-check-filter-mvc-grid
My filterable grid column code:
columns.Bound(c => c.WallThickness).Format("{0:0.000}").Filterable(ftb =>
{
ftb.Multi(true);
ftb.DataSource(ds => ds
.Custom()
.Type("Json")
.Transport(t => t.Read("SortWallThickness", "Materials"))
.Schema(s => s
.Data("Data"))
.Sort(sort => { sort.Add("WallThickness").Ascending();
})
);
})
My controller code:
public ActionResult SortWallThickness([DataSourceRequest] DataSourceRequest request)
{
List<string> data = WeldObject.GetWT(0);
return Json(new[] { data }.ToDataSourceResult(request, ModelState));
}
Appreciate your help,
Carolyn
9 Answers, 1 is accepted
Could you try setting the DataSource type to "aspnetmvc-ajax":
columns.Bound(c => c.WallThickness).Format(
"{0:0.000}"
).Filterable(ftb =>
{
ftb.Multi(
true
);
ftb.DataSource(ds => ds
.Custom()
.Type(
"aspnetmvc-ajax"
)
.Transport(t => t.Read(
"SortWallThickness"
,
"Materials"
))
.Schema(s => s
.Data(
"Data"
))
.Sort(sort => { sort.Add(
"WallThickness"
).Ascending();
})
);
})
This will ensure that the sort parameters will be passed in the correct format to the server.
Regards,
Tsvetina
Progress Telerik

Hi Tsvetina,
Unfortunately that did not work...I'm still getting the HTTP 500 error saying it cannot find the transport code "SortWallThickness" (upon inspection in the browser).
The weird thing is, when I run the debugger, I can see that the SortWallThickness code is executed. Could there be something wrong with that code - specifically returning Json?
public ActionResult SortWallThickness([DataSourceRequest] DataSourceRequest request)
{
List<string> data = WeldObject.GetWT(0);
return Json(new[] { data }.ToDataSourceResult(request, ModelState));
}
Thanks for your help,
Carolyn
I tried an identical column definition and it works on my side:
@(Html.Kendo().Grid<TelerikMvcApp32.Models.OrderViewModel>()
.Name(
"grid"
)
.Columns(columns =>
{
columns.Bound(p => p.OrderID).Filterable(
false
);
columns.Bound(p => p.OrderDate).Format(
"{0:MM/dd/yyyy}"
);
columns.Bound(c => c.Freight).Format(
"{0:0.000}"
).Filterable(ftb =>
{
ftb.Multi(
true
);
ftb.DataSource(ds => ds
.Custom()
.Type(
"aspnetmvc-ajax"
)
.Transport(t => t.Read(
"Orders_Read"
,
"Grid"
))
.Schema(s => s
.Data(
"Data"
))
.Sort(sort =>
{
sort.Add(
"Freight"
).Ascending();
})
);
});
columns.Bound(p => p.ShipName).Width(150);
columns.Bound(p => p.ShipCity).Width(150);
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.HtmlAttributes(
new
{ style =
"height:550px;"
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action(
"Orders_Read"
,
"Grid"
))
)
)
public
ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request)
{
var result = Enumerable.Range(0, 50).Select(i =>
new
OrderViewModel
{
OrderID = i,
Freight = i * 10,
OrderDate = DateTime.Now.AddDays(i),
ShipName =
"ShipName "
+ i,
ShipCity =
"ShipCity "
+ i
});
return
Json(result.ToDataSourceResult(request));
}
Could you show me your full Grid declaration with the latest changes and a screenshot of the error that you see in the browser console? Also, check if there is any additional information in the Response of the failed request (you can inspect it in the Network tab in the browser developer tools).
Regards,
Tsvetina
Progress Telerik

Hi Tsvetina,
Thank you for all your help. In looking at how you coded your ActionResult I was able to get it to work.
Here is how I changed my controller side code following your example:
public ActionResult SortWallThickness([DataSourceRequest] DataSourceRequest request)
{
List<string> data = WeldObject.GetWT(0);
var result = data.Select(x => new WallThicknessVM()
{
WallThickness = Convert.ToDouble(x)
});
return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
Basically I created a view model with just the property WallThickness in it and I added the JsonRequestBehavior.AllowGet in the return statement.
Much Thanks,
Carolyn

Hello this is a new question related to the above question:
When I call the .Transport() function as documented above, is there a way to pass in a parameter?
I would like the parameter to be the filter selections from a different "filterable" column.
Is this possible?
My goal is to limit the values in a filter based on other column filter selections...
To filter the current column data based on other columns, it is better to declare a standalone DataSource, so you can access and filter it when there is a new filter applied in the Grid.
I am attaching a sample project, where the multi-checkbox filter DataSource is filtered on Grid filter. In this specific example, a single DataSource is shared between all columns that have multi-checkbox filters, but the same approach is applicable with multiple DataSources, too.
The main logic follow below:
@(Html.Kendo().DataSource<TelerikMvcApp3.Models.OrderViewModel>()
.Name(
"dataSource1"
)
.Ajax(dataSource => dataSource
.Read(read => read.Action(
"Orders_Read"
,
"Grid"
))
.Sort(sort=>sort.Add(
"ShipName"
).Ascending())
)
)
<div class=
"container-fluid"
>
<div class=
"row"
>
<div class=
"col-xs-18 col-md-12"
>
@(Html.Kendo().Grid<TelerikMvcApp3.Models.OrderViewModel>()
.Name(
"grid"
)
.Columns(columns =>
{
columns.Bound(p => p.OrderID).Filterable(
false
);
columns.Bound(p => p.Freight).Filterable(f => f.Multi(
true
).DataSource(
"dataSource1"
));
columns.Bound(p => p.OrderDate).Format(
"{0:MM/dd/yyyy}"
);
columns.Bound(p => p.ShipName).Filterable(f => f.Multi(
true
).DataSource(
"dataSource1"
));
columns.Bound(p => p.ShipCity).Filterable(f => f.Multi(
true
).DataSource(
"dataSource1"
));
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.Events(e=>e.Filter(
"onFilter"
))
.HtmlAttributes(
new
{ style =
"height:550px;"
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action(
"Orders_Read"
,
"Grid"
)))
)
</div>
</div>
</div>
<script>
function
onFilter(e) {
var
dataSource =
this
.dataSource,
newFilters = e.filter,
currentFilters = dataSource.filter(),
field = e.field;
// if filters are cleared, clear them from the external DataSource, too
if
(!newFilters) {
removeFiltersForField(currentFilters, field);
dataSource1.filter(currentFilters);
return
;
}
// if new filters are aplied and there are existing filters in the DataSource, join them
if
(currentFilters && currentFilters.filters) {
removeFiltersForField(currentFilters, field);
currentFilters.filters.push(newFilters);
}
// if there are no existing filter, build the initial Grid filter expression
else
{
currentFilters = { logic:
"or"
, filters: [newFilters] };
}
dataSource1.filter(currentFilters);
}
function
removeFiltersForField(expression, field) {
if
(expression.filters) {
expression.filters = $.grep(expression.filters,
function
(filter) {
removeFiltersForField(filter, field);
if
(filter.filters) {
return
filter.filters.length;
}
else
{
return
filter.field != field;
}
});
}
}
</script>
Regards,
Tsvetina
Progress Telerik

Thanks, this was helpful. I do have 1 question though regarding the values repeating. Can we somehow make values unique in filter menu pop up, like it is when we are not using external datasource. See attached the image from your solution. Basically I changed your code to have only shipname and not shipname1,2,3., Can we make shipname appear only once ?

Also the field I would like to apply custom sorting (by implementing IComparer or something), is that possible ? currently in your code you have
"DataSource<TelerikMvcApp3.Models.OrderViewModel>()
.Name("dataSource1")
.Ajax(dataSource => dataSource
.Read(read => read.Action("Orders_Read", "Grid"))
.Sort(sort=>sort.Add("ShipName").Ascending())
)"
is it possible to have sort here implement my sorting?
Yes, you can return unique values if you apply a Distinct operator with a custom comparer in the controller method that returns the checkboxes data. You can see an example in this demo:
Grid / Filter Multi Checkboxes
See how the DataSource of the Server Operations Grid calls the Unique method on the controller and passes it the current column field:
columns.Bound(e => e.Country).Width(220).Filterable(ftb => ftb.Multi(
true
).ItemTemplate(
"itemTemplate"
)
.DataSource(ds => ds.Read(r => r.Action(
"Unique"
,
"Grid"
).Data(
"{ field: 'Country' }"
)))
);
The Unique method looks like this:
public
ActionResult Unique(
string
field)
{
var result = GetEmployees().Distinct(
new EmployeeComparer(field));
return
Json(result, JsonRequestBehavior.AllowGet);
}
Inside it, you can also apply your custom sorting.
The EmployeeComparer compares two employee models only by the field that is passed to it:
public
class
EmployeeComparer : IEqualityComparer<EmployeeViewModel>
{
private
string
field;
private
PropertyInfo prop;
public
EmployeeComparer(
string
field)
{
this
.field = field;
prop =
typeof
(EmployeeViewModel).GetProperty(field);
}
public
bool
Equals(EmployeeViewModel x, EmployeeViewModel y)
{
var valueX = prop.GetValue(x,
null
);
var valueY = prop.GetValue(y,
null
);
if
(valueX ==
null
)
{
return
valueY ==
null
;
}
return
valueX.Equals(valueY);
}
public
int
GetHashCode(EmployeeViewModel obj)
{
var value = prop.GetValue(obj,
null
);
if
(value ==
null
)
{
return
0;
}
return
value.GetHashCode();
}
}
As you probably noticed already, this will work properly for multiple columns only if you declare a separate DataSource in each column, so that you can pass the field name based on the current column.
Regards,
Tsvetina
Progress Telerik