This is a migrated thread and some comments may be shown as answers.

Cascading multiselect problem

3 Answers 350 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
Jelly Master
Top achievements
Rank 1
Jelly Master asked on 14 Feb 2014, 02:37 AM
I am currently using the multi select for the first time and am encountering a problem with the scenario I am using.

I have the following cshtml page: ​

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
<h2>Index</h2>
 
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
 
    @(Html.Kendo().Grid<InclusionManagerMVC.Models.HouseModels.HouseModel>()
.Name("HouseGrid")
    .HtmlAttributes(new { style = "height:600px;" })
.ToolBar(toolbar =>
{
    toolbar.Create();
})
.Columns(columns =>
{
    columns.Bound(c => c.ID).Visible(false);
    columns.Bound(c => c.Name).Title("House Name");
    columns.Bound(c => c.TooltipText).Title("Description");
    columns.Bound(c => c.Active).Title("Enabled");
 
    columns.Command(c => c.Edit());
})
.Editable(edit =>
{
    edit.TemplateName("HouseModel").Mode(GridEditMode.PopUp);
})
.DataSource(datasource =>
{
    datasource.Ajax()
        .Create(create => create.Action("Create_House", "Houses", new { area = "Administration" }).Data("sendAntiForgery"))
        .Read(read => read.Action("Read_House", "Houses", new { area = "Administration" }))
        .Update(update => update.Action("Update_House", "Houses", new { area = "Administration" }).Data("sendAntiForgery"))
        .Model(model =>
        {
            model.Id(field => field.ID);
            model.Field(field => field.ID).DefaultValue(Guid.NewGuid());
            model.Field(field => field.Name);
 
            model.Field(field => field.Active).DefaultValue(true);
            model.Field(field => field.TooltipText).DefaultValue(string.Empty);
            model.Field(field => field.SchoolsIdList).DefaultValue(new List<InclusionManagerMVC.Models.SchoolModels.SchoolsModel>());
            model.Field(field => field.TenantIdList).DefaultValue(new List<InclusionManagerMVC.Models.TenantModels.TenantsModel>());
        })
        .Events(events => events.Error("error_handler"));
 
 
})
.Pageable(page => page.PageSizes(new int[] { 10, 20, 50, 100, 250, 1000 }).Refresh(true))
.Sortable()
.Groupable()
.Filterable()
.Scrollable()
.ColumnMenu()
    )
}
 
<script type="text/javascript">
    function tenantsfilter()
    {
        var multiSelect = $("#TenantIdList").data("kendoMultiSelect");
        var values = multiSelect.value($("#value").val());
        console.log(values.length);
         
        return { tenants: values.toString() };
 
    }
 
    function refresh_multiSelect(e)
    {
        console.log(e);
 
        $("#SchoolsIdList").data("kendoMultiSelect").dataSource.read();
        
    }
 
</script>


I am then using this editor on the screen:
@model InclusionManagerMVC.Models.HouseModels.HouseModel
 
 
@Html.HiddenFor(m => m.ID)
 
 
<div class="form-horizontal" role="form" style="padding:10px;">
    <div class="form-group">
        @Html.LabelFor(m => m.Name, new { @class = "form-label col-lg-2" })
        <div class="col-lg-6">
            @Html.TextBoxFor(m => m.Name, new { @class = "form-control", placeholder = "Enter name of the house" })
        </div>
    </div>
 
    <div class="form-group">
        @Html.LabelFor(m => m.TooltipText, new { @class = "form-label col-lg-2" })
        <div class="col-lg-6">
            @Html.TextAreaFor(m => m.TooltipText, new { @class = "form-control", placeholder = "Enter a description about this house" })
        </div>
    </div>
 
    <div class="form-group">
        @Html.LabelFor(m => m.Active, new { @class = "form-label col-lg-2" })
        <div class="col-lg-6">
            @Html.CheckBoxFor(m => m.Active)
        </div>
    </div>
 
    <div class="form-group">
         @Html.LabelFor(m => m.TenantIdList, new { @class = "form-label col-lg-2" })
        <div class="col-lg-6">
            @(
                Html.Kendo().MultiSelectFor(m => m.TenantIdList)
                .DataTextField("Name")
                .DataValueField("ID")
                .DataSource(datasource =>
                {
                    datasource.Read(read => read.Action("GetTenants", "Houses", new { area = "Administration" }));
                })
                .Placeholder("Select School Groups")
                .IgnoreCase(true)
                .HighlightFirst(true)
             )
        </div>
    </div>
 
 
    <div class="form-group">
        @Html.LabelFor(m => m.SchoolsIdList, new { @class = "form-label col-lg-2" })
        <div class="col-lg-8">
            @(
 Html.Kendo().MultiSelectFor(m => m.SchoolsIdList)
                .DataTextField("Name")
                .DataValueField("ID")
                .AutoBind(false)
                 
                .DataSource(datasource =>
                {
                    datasource.Read(read => read.Action("GetSchools", "Houses", new { area = "Administration" })
                        .Data("tenantsfilter"))
                        .ServerFiltering(true)
                        .Events(events => events.Error("error_handler").Change("refresh_multiSelect"));
                })
                .Placeholder("Select Schools")
                .IgnoreCase(true)
                .HighlightFirst(true)
                .ItemTemplate("<span class=\"label label-info\">#: data.Name#</span><span class=\"label label-default\">(#:data.TenantName#)</span> ")
            )
        </div>
    </div>
 
 
 
 
 
    @Html.Partial("_ErrorPanel")
</div>


This then calls the appropriate controller below:


public JsonResult Read_House([DataSourceRequest] DataSourceRequest request)
       {
           this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
           List<HouseModel> model = new List<HouseModel>();
           try
           {
               model = houseSvc.GetHousesList();
           }
           catch (Exception error)
           {
               throw error;
           }
 
           return Json(model.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
 
       }
 
 
       public JsonResult GetTenants()
       {
           this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
           List<TenantsModel> model = tenantSvc.GetTenantsList(true);
            
           return Json(model, JsonRequestBehavior.AllowGet);
 
       }
 
       public JsonResult GetSchools(string tenants)
       {
           this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
           List<string> tenantStringList = tenants.Split(',').ToList();
 
           List<TenantsModel> tenants2 = tenantSvc.GetTenantsList(true, tenantStringList);
 
            
 
 
            
           List<SchoolsModel> model = schoolSvc.GetSchoolsList(true, tenants2);
 
 
 
 
           return Json(model, JsonRequestBehavior.AllowGet);
 
       }

So when I go to my editor and select the first multiselect item I get the drop down option but when I select the second one the change event is constantly firing.

I know it is because of the datasource.read() action being performed which is causing this but how do I prevent this.


What I need to be able to do is select the values in the first multi-select (tenantsIdList) and then it rebind the options back to the SchoolsIdList with the found values.

In addition to this I need to be able to remove items from the (SchoolsIdList) if the corresponding (tenantsIdList) is removed.

For example in the tenants options we have

Tenant 1
Tenant 2
Tenant 3
.....



In the schools list we have

School 1 (which is associated with Tenant 1)
School 2 (which is associated with Tenant 2)
School 3 (which is associated with Tenant 3)
.......

So if I select "Tenant 1" in the first multi select I would only see "School 1" in the second multi select

if I then selected "Tenant 2" in the first multi select I would now see School 1 and School 2.

But then if I de-selected "Tenant 1" I would only want School 2 to be available in addition if School 1 had been selected as a value then this should be removed from the list of selected values.

Any assistance would be greatly received.





3 Answers, 1 is accepted

Sort by
0
Jelly Master
Top achievements
Rank 1
answered on 14 Feb 2014, 05:12 PM
well after having some sleep I have found the issue.

I applied the event handler on the datasource rather than the control itself. Obvious when I think about it. #facepalm

Now to finish of the rest of the functionality 
0
Jelly Master
Top achievements
Rank 1
answered on 14 Feb 2014, 06:30 PM
just in case anyone else is looking to do something similar here is some code to point you in the right direction hopefully.

<script type="text/javascript">
    function tenantsfilter()
    {
         
        var values = getMultiSelectValues("TenantIdList");
         
         
        return { tenants: values.toString() };
 
    }
 
    function refresh_multiSelect(e)
    {
        $("#SchoolsIdList").data("kendoMultiSelect").dataSource.read();
         
    }
 
    function tenant_multiSelect(e)
    {
        var item = getMultiSelectValues("TenantIdList");
        var schoolsList = getMultiSelectValues("SchoolsIdList");
 
        if (item.length > 0 && schoolsList.length > 0 )
        {
            //cycle through and remove any schools that should not be there.
            //first we need to get the schools that are associated with the remaining tenants
 
            $.getJSON("GetSchools", tenantsfilter(), function (data)
            {
                //console.log(data);
 
                var newSchoolList = new Array();
                 
 
                for (var i = 0; i < data.length; i++)
                {
                    var school  = data[i];
 
                    //console.log(id);
 
                    var foundValue = $.inArray(school.ID, schoolsList, 0);
 
                    if(foundValue > -1)
                    {
                        //console.log(school);
                        newSchoolList.push(school.ID);
                         
                    }
 
                }
 
                setMultiSelectValue("SchoolsIdList", newSchoolList);
 
            })
 
 
             
 
 
        }
        else
        {
            //remove items from lower drop down list.
            setMultiSelectValue("SchoolsIdList", []);
 
        }
 
       // console.log(item);
 
    }
 
 
    function getMultiSelectValues(multiSelectControl) {
    var multiSelect = $("#" + multiSelectControl).data("kendoMultiSelect");
    var values = multiSelect.value($("#value").val());
    return values;
 
}
 
 
function setMultiSelectValue(multiSelectControl, values) {
    var multiSelect = $("#" + multiSelectControl).data("kendoMultiSelect");
    multiSelect.value(values);
 
}
 
 
</script>

Maybe someone with a bit more javascript knowledge could make this a bit cleaner but it seems to work for me at the moment.


0
Jason
Top achievements
Rank 2
answered on 18 Oct 2016, 04:38 AM

Jelly Master,

This is indeed the solution to kendoMultiSelect cascading.  I have searched and searched, and literally hit every other post on this subject and finally, when I got to this one, I found the solution.  Thank you so much for your help!!!

Tags
MultiSelect
Asked by
Jelly Master
Top achievements
Rank 1
Answers by
Jelly Master
Top achievements
Rank 1
Jason
Top achievements
Rank 2
Share this question
or