Cascading multiselect problem

4 posts, 0 answers
  1. Jelly Master
    Jelly Master avatar
    39 posts
    Member since:
    Oct 2010

    Posted 13 Feb 2014 Link to this post

    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.





  2. Jelly Master
    Jelly Master avatar
    39 posts
    Member since:
    Oct 2010

    Posted 14 Feb 2014 in reply to Jelly Master Link to this post

    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 
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Jelly Master
    Jelly Master avatar
    39 posts
    Member since:
    Oct 2010

    Posted 14 Feb 2014 in reply to Jelly Master Link to this post

    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.


  5. Jason
    Jason avatar
    1 posts
    Member since:
    Oct 2015

    Posted 17 Oct in reply to Jelly Master Link to this post

    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!!!

Back to Top
UI for ASP.NET MVC is VS 2017 Ready