checkboxes not working in treeview

8 posts, 2 answers
  1. Scott
    Scott avatar
    28 posts
    Member since:
    May 2015

    Posted 30 Oct 2015 Link to this post

    When I try to add checkboxes to the TreeView,devtools int he browser show I am getting "Invalid Template"

    This works (but no checkboxes).  But if I uncomment the ".Checkboxes part, it throws error.  I have tried many variants, including just ".Checkboxes(true)".

    <script id="UserDetailsTemplate" type="text/kendo-tmpl">

        @*@Html.Kendo().TextBox().Value("foo #= User_Login#").Name("yoda_#=User_Login#")*@
        @(Html.Kendo()
              .TabStrip()
              .Name("userTabStrip_#=Person_ID#")
              .SelectedIndex(0)
              .Items((items) =>
                     {
                         items.Add()
                              .Text("Contact Info");
                         items.Add()
                              .Text("Permissions")
                              .Content(obj => Html.Kendo()
                                                  .TreeView()
                                                  .DataTextField("Name")
                                                  .Name("userModulePermissions#=Person_ID#")
                                                  //.Checkboxes(cbxConfig => cbxConfig.Enabled(true)
                                                  //                                  .CheckChildren(true)
                                                  //                                  .Name("checkedNodes"))
                                                  .DataSource(d => d.Read("PermissionsTree_Read",
                                                                          "SettingsUsers"))
                                                  .ToClientTemplate());
                         items.Add()
                              .Text("Group Membership");
                     })
              .ToClientTemplate()
              )
    </script>

    Here is the action the provides the tree data:

             public JsonResult PermissionsTree_Read(long? id)
            {
                var moduleId = id;
                var tracDB = new TRACEntities();
                // because modules & permissions are not same thing, we have to distinguish what "level" we are at in the tree
                // modules are root level, permissions (sub_sections) are next (leaf) level
                if (moduleId == null)
                {
                    var result = GetOrgModules()
                        .Select(m => new {   
                                             id = m.Module_Type_ID,
                                             Name = m.Module_Type_Name,
                                             hasChildren = GetUserModuleSubsectionPermissions(m.Module_Type_ID).Any(),
                                             @checked = false
                        });
                    return Json(result,
                                JsonRequestBehavior.AllowGet);
                }
                else
                {
                    var result = GetUserModuleSubsectionPermissions((long) moduleId)
                        .Select(p => new {
                                             id = p.Sub_Section_Type_Id,
                                             Name = p.Sub_Section_Type_Desc,
                                             hasChildren = false,  //always leaves
                                             //@checked = false  //I have tried with and without this line -- it was just a guess that this was needed
                                         });
                    return Json(result,
                                JsonRequestBehavior.AllowGet);
                }
            }

     

  2. Scott
    Scott avatar
    28 posts
    Member since:
    May 2015

    Posted 30 Oct 2015 Link to this post

    Here is the error message:

     Error: Invalid template:' <div class="k-tabstrip-wrapper"><div class="k-widget k-tabstrip k-header" id="userTabStrip_#=Person_ID#"><ul class="k-reset k-tabstrip-items"><li class="k-item k-state-default k-state-active"><span class="k-link">Contact Info</span></li><li class="k-item k-state-default"><a class="k-link" href="\#userTabStrip_#=Person_ID#-2">Permissions</a></li><li class="k-item k-state-default"><span class="k-link">Group Membership</span></li></ul><div class="k-content k-state-active" id="userTabStrip_#=Person_ID#-1" style="display:block"></div><div class="k-content" id="userTabStrip_#=Person_ID#-2"><div class="k-widget k-treeview k-reset" id="userModulePermissions#=Person_ID#"></div><script> jQuery(function(){jQuery("\#userModulePermissions#=Person_ID#").kendoTreeView({"dataSource":{"transport":{"read":{"url":"/TRAC/TracMvc/SettingsUsers/PermissionsTree_Read"}},"schema":{"model":{}}},"checkboxes":{"name":"checkedNodes","template":"\u003cinput type=\u0027checkbox\u0027 name=\u0027#= treeview.checkboxes.name #\u0027 #= item.checked ? \u0027checked\u0027 : \u0027\u0027 # value=\u0027#= item.id #\u0027 /\u003e","checkChildren":true},"dataTextField":["Name"]});}); <\/script></div><div class="k-content" id="userTabStrip_#=Person_ID#-3"></div></div></div><script> jQuery(function(){jQuery("\#userTabStrip_#=Person_ID#").kendoTabStrip({});}); <\/script> ' Generated code:'var $kendoOutput, $kendoHtmlEncode = kendo.htmlEncode;with(data){$kendoOutput='\n \n <div class="k-tabstrip-wrapper"><div class="k-widget k-tabstrip k-header" id="userTabStrip_'+(Person_ID)+'"><ul class="k-reset k-tabstrip-items"><li class="k-item k-state-default k-state-active"><span class="k-link">Contact Info</span></li><li class="k-item k-state-default"><a class="k-link" href="#userTabStrip_'+(Person_ID)+'-2">Permissions</a></li><li class="k-item k-state-default"><span class="k-link">Group Membership</span></li></ul><div class="k-content k-state-active" id="userTabStrip_'+(Person_ID)+'-1" style="display:block"></div><div class="k-content" id="userTabStrip_'+(Person_ID)+'-2"><div class="k-widget k-treeview k-reset" id="userModulePermissions'+(Person_ID)+'"></div><script>\n\tjQuery(function(){jQuery("#userModulePermissions'+(Person_ID)+'").kendoTreeView({"dataSource":{"transport":{"read":{"url":"/TRAC/TracMvc/SettingsUsers/PermissionsTree_Read"}},"schema":{"model":{}}},"checkboxes":{"name":"checkedNodes","template":"\u003cinput type=\u0027checkbox\u0027 name=\u0027'+( treeview.checkboxes.name )+'\u0027 '+( item.checked ? \u0027checked\u0027 : \u0027\u0027 )+' value=\u0027'+( item.id )+'\u0027 /\u003e","checkChildren":true},"dataTextField":["Name"]});});\n<\/script></div><div class="k-content" id="userTabStrip_'+(Person_ID)+'-3"></div></div></div><script>\n\tjQuery(function(){jQuery("#userTabStrip_'+(Person_ID)+'").kendoTabStrip({});});\n<\/script>\n';}return $kendoOutput;'

    ...ath.floor(f.length/2),e}catch(a){throw Error(r.format("Invalid template:'{0}' Ge...

  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Answer
    Dimo
    Admin
    Dimo avatar
    8330 posts

    Posted 02 Nov 2015 Link to this post

    Hi Scott,

    The problem is caused by the fact that the TreeView uses internally a Kendo UI template for the checkboxes, and the # characters inside this template are not escaped (and they cannot be escaped automatically).

    http://docs.telerik.com/kendo-ui/framework/templates/overview#template-syntax

    Generally, a possible approach is to escape the nested template expressions manually with custom code like this:

    @{
        var treeView = Html.Kendo().TreeView()
                        .Name("TREEVIEW-NAME")
                        .ToClientTemplate().ToHtmlString().Replace("#", "\\#").Replace(@"jQuery(""\\#TREEVIEW-NAME"")", @"jQuery(""\\#TREEVIEW-NAME"")");
    }
    <script id="template" type="text/kendo-tmpl">
     
        @Html.Raw(treeView)
     
    </script>


    However, this will be rather cumbersome in a Grid detail template, because you need unique TreeView names, so my primary recommendation is to use client-side TreeView initialization syntax (i.e HTML + Javascript), which will allow you to have full control over the HTML markup and Javascript initialization statement.

    http://docs.telerik.com/kendo-ui/api/javascript/ui/treeview

    Regards,
    Dimo
    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
  5. Scott
    Scott avatar
    28 posts
    Member since:
    May 2015

    Posted 02 Nov 2015 Link to this post

    I'm not sure I understand.  It seemed to work fine without checkboxes.  Only with checkboxes does the problem arise.  Your answer seems to indicate this should be a problem with all treeviews embedded within a template.

    I am starting to think that the problem of "escaping" with nested templates is just too much of a hassle.  

    But this seriously cripples the value of the MVC kendo() helpers in razor pages, the point of which is to avoid writing javascript.

  6. Scott
    Scott avatar
    28 posts
    Member since:
    May 2015

    Posted 02 Nov 2015 in reply to Dimo Link to this post

     The other thing I would ask is isn't this a bug in .ToClientTemplate()?  Shouldn't it recognize a nested template & escape as needed?

  7. Answer
    Dimo
    Admin
    Dimo avatar
    8330 posts

    Posted 04 Nov 2015 Link to this post

    Hi Scott,

    When TreeView checkboxes are enabled, the widget generates and renders a Kendo UI template that includes expressions with # characters. These characters should be treated as literals by the Grid, however, they are not escaped, so the Grid tries to evaluate the TreeView's template expressions as well, which causes the Javascript error.

    The TreeView itself is not able to escape its template expressions automatically, because the widget is not aware of the exact level of its template nesting. In other words, the TreeView is not aware if it is part of a first-level client template, or if it is placed in a nested client template, which is injected in another client template, and so on.

    The main task of .ToClientTemplate() is to escape the closing </script> tag that the widget renders.

    Regards,
    Dimo
    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
  8. Scott
    Scott avatar
    28 posts
    Member since:
    May 2015

    Posted 04 Nov 2015 Link to this post

    Is there a general guide or tutorial on nesting of client templates, and how to escape them to the correct number of levels?

    Or is the best advice to not use client templates for complicated nesting of widgets, and take a different approach?

  9. Dimo
    Admin
    Dimo avatar
    8330 posts

    Posted 06 Nov 2015 Link to this post

    Hi Scott,

    The rule of thumb is to add additional "\\" for each new level of client template nesting. I am afraid there is no automated way to measure the nesting level programmatically, so the number of backslashes should be hard-coded.

    http://docs.telerik.com/kendo-ui/framework/templates/overview#escaping-hash-literals

    The above procedure is possible to follow in most cases, so client templates can be used in complicated scenarios as well. The problem in this particular case is that the TreeView defines a client template, which you don't have control over, so you can't prepend backslashes, depending on the nesting level.

    Regards,
    Dimo
    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