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

how to "bind" treeview checkboxes to field in model

3 Answers 505 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Scott
Top achievements
Rank 1
Scott asked on 02 Nov 2015, 11:55 PM

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.

3 Answers, 1 is accepted

Sort by
0
Alex Gyoshev
Telerik team
answered on 04 Nov 2015, 09:20 AM

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
0
Scott
Top achievements
Rank 1
answered on 04 Nov 2015, 09:13 PM

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;
        }

0
Alex Gyoshev
Telerik team
answered on 06 Nov 2015, 10:15 AM
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
Tags
TreeView
Asked by
Scott
Top achievements
Rank 1
Answers by
Alex Gyoshev
Telerik team
Scott
Top achievements
Rank 1
Share this question
or