Search code examples
asp.net-mvctelerikkendo-grid

Kendo MVC how to bind custom toolbar action in child grids


Objective: bind detail grids' custom toolbar actions to pass the id of the parent row to the client-side script.

master-detail grids

Each master row has 0-many details, displayed upon expanding the row. The details are another grid bound to the parent row using kendo's client templating.

grids

master grid

     @(Html.Kendo().Grid<ConfigurationRuleViewModel>()
          .Name("configurationRuleGrid")
          .Columns(columns =>
          ...)
          // detail grid
          .ClientDetailTemplateId("configRuleDetailTemplate")
        )

detail viewmodel

ConfigurationId is the property needed to be bound and passed to the add button's onclick event of the subgrid for each row.

  public class RuleViewModel
  {
    public long Id { get; set; }
    [Required]
    public int ConfigurationId { get; set; }
    ...
  }       

detail grid (kendo client template)

   <script id="configRuleDetailTemplate" type="text/kendo-template">
       @(Html.Kendo().Grid<RuleViewModel>()
           .Name("grid_#=Id#")
           .Columns(columns =>
            ...
           )//
           .ToolBar(commands =>
                    commands.Template("<a class='btnNewRule k-button k-button-icontext' onclick='loadNewRule(\\#=ConfigurationId \\#)' title='Add new rule'></span>Add</a>"))
           ...
           .DataSource(dataSource => dataSource
           ...
           )
          .ToClientTemplate())
  </script>

what I tried

  • binding to the buttons individually use the document.ready event

    //attempt 1 (tried many different selectors, same result) var addBtns = $("a.btnNewRule");

    // can't find buttons if($.isArray(addBtns)) { $(addBtns).each(function(_, btn){ btn.on("click",function () { loadNewRule(this); }); }); }

    //attempt 2 // finding from the grid context, toolbars // still can't find buttons ruleGrid.find(".k-grid-toolbar").on("click", ".btnNewRule", function (e) { loadNewRule(e); });

testing the selectors in the dev console show that the elements are not available at the time so the only option appears to be binding in the details grid using a custom toolbar - rendering race condition.

  • current implementation: attempting to bind the click event using the viewmodel property ConfigurationId

    onclick='loadNewRule(\#=ConfigurationId \#)'

BUT, the syntax is bogus and generates an [expected] error:

  Uncaught SyntaxError: Invalid or unexpected token

What is the correct way to bind the property in the client template.

NOTE: the client template uses inline editing but the add will use a popup with custom editors, hence the need to bind as attempting.

Open to different ways to achieve the objective.


Solution

  • This seems like the ghetto way to do it but it works. Anyone have a better, more kendo way please post. A solution, is to pass the button reference this to the load function which uses the button to locate the row that contains the parent element (which contains the property needed).

    custom toolbar, onlick definition

      //detail grid command definitions
      ...
       commands.Template("<a class='btnNewRule k-button k-button-icontext' onclick='loadNewRule(this)' title='Add new rule'></span>Add</a>"))
      ...
    

    js helper function to find the parent id

    common pattern to find related items in kendo

       function getCurrentParentConfigurationId(source) {
            const row = $(source).closest("tr");
            const grid = $("#configurationRuleGrid").data("kendoGrid");
            const dataItem = grid.dataItem(row);
    
            return dataItem.Id;
       }