how to "bind" treeview checkboxes to field in model

4 posts, 0 answers
  1. Scott
    Scott avatar
    28 posts
    Member since:
    May 2015

    Posted 02 Nov 2015 Link to this post

    I wish to connect the treeview checkboxes to an "enabled" field for records in my database.

    Specifically, when a checkbox is clicked, I want to all an action to update the corresponding enabled field.

    Also, with checkchildren(true), I want to likewise update the enabled field of all children.

    What are the basics of how to do this?

    The only demo using checkboxes also uses hard-coded tree items, with no connection to remote data.

  2. Alex Gyoshev
    Admin
    Alex Gyoshev avatar
    2500 posts

    Posted 04 Nov 2015 Link to this post

    Hello Scott,

    I am afraid that the TreeView checkboxes can only be bound to the checked field at this time. Binding them to another field is not supported by the widget.

    Regards,
    Alex Gyoshev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Scott
    Scott avatar
    28 posts
    Member since:
    May 2015

    Posted 04 Nov 2015 Link to this post

    Actually, with server side binding .BindTo(), I was able to do what I needed.  Although my current solution is probably not the best way.

    While explicitly binding the item.checked to a dataSource field may not be supported.  There really needs to be a demo which both sets the checkboxes based on server side data (and "enabled" field or similar), and updates the server side data when user checks/unchecks a box. Preferably a version with checkedchildren(true).  Also preferrably a version with an ajax dataSource.

    Please advise whether this solution is a "good" way to achieve the desired result with telerik treeview.

    Here is my solution, for the sake of others with similar question.

    The "tree" here is only two levels: modules & subsectionPermissions, which in my case have different viewmodel classes, but this is a minor complication and not important.

    Only the leaves of the tree (2nd level) need checks, because the treeview automagically sets the checkes/unchecked/mixed status of the parent checkboxes.

    I have bolded the parts that may be difficult to discover:

    • How to set the item.checked of items when tree is populated with data
    • assign the items.id, checked, etc., from your own data fields using .BindTo(... mappings.For(...) ...)​
    • How to respond to event of item being checked/unchecked
    • How to get the values of fields item.id and item.checked for the node that was checked/unchecked
    • Do an ajax call to action which updates the database and redraws the treeview.
    • Bind to a tree structure with that can have different data types for nodes.

    This is a partial view:

      

    @model UserPermissionViewModel
    <script>
        function onPrivilegeCheck(e) {
            var treeView = $("#userPermissionsTree").data("kendoTreeView");
            //ajax call to reload the tree...
            var nodeData = treeView.dataItem(e.node);
            $.ajax({
                type: 'GET',
                url: 'UserPrivileges',  // same action that populates the tree in the first place, returns this partial view
                data: {
                    userId: @Model.userId,
                    checkedItemId: nodeData.id,
                    isChecked: nodeData.checked
                },
                dataType: 'json',
                success: function(result) { $('#ajaxifiedDiv').html(result) } // redraw the tree on success

                //error: should put an error handler in here
            });
        }
    </script>
    <div id="ajaxifiedDiv">
        @*OK, doing the treeview a completely different way*@
        @(
        Html.Kendo()
            .TreeView()
            .Name("userPermissionsTree")
            .BindTo((IEnumerable<OrgModulePermissionViewModel>)Model.UserModulePermissions,
                    (NavigationBindingFactory<TreeViewItem> mappings) =>
                    {
                        mappings.For<OrgModulePermissionViewModel>(binding => binding.ItemDataBound((item,
                                                                                                     module) =>
                        {
                            item.Id = module.Module_Type_ID.ToString();
                            item.Text = module.Text;
                        })
                                                                                     .Children(module => module.Items));

                        mappings.For<UserModuleSubsectionPermissionsViewModel>(binding => binding.ItemDataBound((item,
                                                                                                 uPermission) =>
                        {
                            item.Id = uPermission.module_Id.ToString() + "/" + uPermission.Sub_Section_Type_Id.ToString();
                            item.Text = uPermission.Text; // if field already named Text, is mapping needed?
                            item.Checked = uPermission.enabled;
                        }));
                    })
            .Checkboxes(cbxConfig => cbxConfig.Enabled(true)
                                              .CheckChildren(true)
                                              .Name("checkedNodes"))
            .Events(events => events.Check("onPrivilegeCheck"))
        )

    </div>
    --------------------------

    the controller action:

            public ActionResult UserPrivileges(long userId, string checkedItemId = null, bool isChecked = false)
            {
                // logic to update the database when the option parameters are not null goes here
                return PartialView(new UserPermissionViewModel() {
                                                                     userId = userId,
                                                                     orgId = Utility.SV.OrgId,
                                                                     UserModulePermissions = GetOrgModuleUserPermissions(userIdWeNeedPermissionsFor: userId)
                                                                 });
            }​

            public IEnumerable<UserModuleSubsectionPermissionsViewModel> GetUserModuleSubsectionPermissions(long moduleId,
                                                                                                            long userId)
            {
                var tracDb = new TRACEntities();
                var allSubsectionPerms = from sst in tracDb.Sub_Section_Type.Where(sst => sst.Module_Type_ID == moduleId)
                                         from u in sst.Users.Where(u => u.User_ID == userId)
                                                      .DefaultIfEmpty()
                                         select new UserModuleSubsectionPermissionsViewModel() {
                                                                                                   module_Id = moduleId,
                                                                                                   Person_ID = userId,
                                                                                                   Sub_Section_Type_Id = sst.Sub_Section_Type_ID,
                                                                                                   Sub_Section_Type_Desc = sst.Sub_Section_Type_Desc,
                                                                                                   enabled = (u != null) // if the user has a mapping to the sub_section_type, the permission for that subsection is enabled
                                                                                               };
                //dummy result
                IEnumerable<UserModuleSubsectionPermissionsViewModel> result = allSubsectionPerms;
                return result;
            }

            public IEnumerable<OrgModulePermissionViewModel> GetOrgModuleUserPermissions(long userIdWeNeedPermissionsFor)
            {
                var tracDb = new TRACEntities();
                long orgId = Utility.SV.OrgId;
                var org = tracDb.Orgs.Single(o => o.Org_ID == orgId);
                var orgModules = org.Module_Type;
                var orgModulesViewModels = orgModules.Select(m => new OrgModulePermissionViewModel() {
                                                                                               Module_Type_ID = m.Module_Type_ID,
                                                                                               Module_Type_Name = m.Module_Type_Name,
                                                                                               Module_Type_Page = m.Module_Type_Page,
                                                                                               Module_Type_Rank = m.Module_Type_Rank,
                                                                                               Items = GetUserModuleSubsectionPermissions(m.Module_Type_ID, userIdWeNeedPermissionsFor)
                });
                return orgModulesViewModels;
            }

  5. Alex Gyoshev
    Admin
    Alex Gyoshev avatar
    2500 posts

    Posted 06 Nov 2015 Link to this post

    Hello Scott,

    Yes, this approach is good -- it will render the server-side checked state to the client-side, and you only use the checked field of the dataItems.

    Regards,
    Alex Gyoshev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
UI for ASP.NET MVC is VS 2017 Ready