I wanted some persistence with Cascading Combo Boxes when using an AJAX data binding.
The solution also needed to be able to pass a 'selected value from the controller handling the data retrieval.
This is what i came up with, hopefully this is useful to someone else aswell
cshtml
Only thing of note here is the jQuery DataBound event that will handle getting the selected value and setting it
ToolsController.cs
Additional bool coloumn in select that will return true only if selected Client/Package Id is = to session var
JS ondatabound events
These functions are called when data is bound to the combo boxes. They get the data object from the AJAX call and return an array of objects, using jQuery Grep, where selected is === true then use the first object found to populate select a default value from the combo.
I initially tried compacting these two functions into one abstracted function and passing the jquery selector reference and selectedObject[].property as variables in the event handler. Evidently passing variable eg (.Events(e => e.DataBound("onDataBoundPackage('var1', 'var2')")) in the databound event handler breaks the databinding.
The solution also needed to be able to pass a 'selected value from the controller handling the data retrieval.
This is what i came up with, hopefully this is useful to someone else aswell
cshtml
Only thing of note here is the jQuery DataBound event that will handle getting the selected value and setting it
<
label
for
=
"Client"
>Client</
label
>
@(Html.Kendo().ComboBox()
.Name("Client")
.Placeholder("Select Client...")
.DataTextField("ClientName")
.DataValueField("ClientID")
.Events(e => e.DataBound("onDataBoundClient"))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetClientsCombo", "Tools");
});
})
)
<
label
for
=
"Package"
>Package</
label
>
@(Html.Kendo().ComboBox()
.Name("Package")
.Placeholder("Select Package...")
.DataTextField("PackageName")
.DataValueField("PackageID")
.Events(e => e.DataBound("onDataBoundPackage"))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetPackagesCombo", "Tools")
.Data("filterPackages");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("Client")
)
Additional bool coloumn in select that will return true only if selected Client/Package Id is = to session var
public
JsonResult GetClientsCombo()
{
int
selectedClientId = Session[
"selectedClientId"
];
var query =
//Linq Query to get results
select
new
{
ClientID = LinqClientIdColumn,
ClientName = LinqClientNameColumn,
Selected = LinqClientIdColumn == selectedClientId
};
return
Json(query, JsonRequestBehavior.AllowGet);
}
public
JsonResult GetPackagesCombo(
int
clients,
string
packageFilter)
{
int
selectedPackageId = Session[
"selectedPackageId"
];
var query =
//Linq Query to get results
select
new
{
PackageID = LinqPackageIdColumn,
PackageName = LinqPackageNameColumn,
Selected = LinqPackageIdColumn == selectedPackageId
};
return
Json(query, JsonRequestBehavior.AllowGet);
}
These functions are called when data is bound to the combo boxes. They get the data object from the AJAX call and return an array of objects, using jQuery Grep, where selected is === true then use the first object found to populate select a default value from the combo.
I initially tried compacting these two functions into one abstracted function and passing the jquery selector reference and selectedObject[].property as variables in the event handler. Evidently passing variable eg (.Events(e => e.DataBound("onDataBoundPackage('var1', 'var2')")) in the databound event handler breaks the databinding.
function
onDataBoundClient() {
var
DataObject = $(
"#Client"
).data(
"kendoComboBox"
).dataSource.data();
var
selectedObject = $.grep(DataObject,
function
(obj) {
return
obj.Selected ===
true
;
});
$(
"#Client"
).data(
'kendoComboBox'
).value(selectedObject[0].ClientID);
};
function
onDataBoundPackage() {
var
DataObject = $(
"#Package"
).data(
"kendoComboBox"
).dataSource.data();
var
selectedObject = $.grep(DataObject,
function
(obj) {
return
obj.Selected ===
true
;
});
$(
"#Package"
).data(
'kendoComboBox'
).value(selectedObject[0].PackageID);
};