kendo-uikendo-gridkendo-asp.net-mvc

How can I create new lines in a Kendo UI grid with both a ClientTemplate and an EditorTemplateName in MVC?


I'm trying to make a Kendo grid for a list of contacts, with the following requirements:

  1. There should be a toolbar button for creating new contacts
  2. There should be an Actions column, with an Edit and Delete button
  3. There should be a column called Contact Groups:
    • In my view model, this is defined as a list of strings
    • While the grid is in Display mode, this should be displayed as a comma separated string
    • While the grid is in Edit mode, this should be a Kendo MultiSelect element, allowing the user to select one or more of a hard coded list of available choices

To accomplish this, this is the view that I've created so far:

@using MyProject.Contacts.Models;
@using Kendo.Mvc.UI;

@{
    ViewBag.Title = "Contacts";
}

<div id="contactsContainer" class="">
    @(Html.Kendo().Grid<ContactsViewModel>()
          .Name("ContactsGrid")
          .Columns(columns =>
          {
              columns.Bound(p => p.ContactName).Title("Contact Name").Width(200);
              columns.Bound(p => p.ContactGroups).ClientTemplate("#= displayContactGroups(ContactGroups)#").EditorTemplateName("ContactGroupsEditor").Title("ContactGroups").Width(200);
              columns.Command(command =>
              {
                  command.Edit().IconClass("k-icon k-i-edit");
                  command.Destroy().IconClass("k-icon k-i-delete");
              }
              ).Title("Actions").Width(200);
          })
          .NoRecords(n => n.Template("No Contacts to display"))
          .ToolBar(tools =>
          {
              tools.Create().Text("Create New Contact");
          })
          .DataSource(dataSource => dataSource
                .Ajax()
                .PageSize(10)
                .Model(model =>
                {
                    model.Id(m => m.kendoId);
                }
                )
                .Create(create => create.Action("CreateContact", "Contacts"))
                .Read(read => read.Action("GetContacts", "Contacts"))
                .Update(update => update.Action("UpdateContact", "Contacts"))
                .Destroy(destroy => destroy.Action("DeleteContact", "Contacts"))

          )

      )

</div>

<script>
    function displayContactGroups(contactGroups) {
        if (contactGroups == null) {
            return "";
        }
        return contactGroups.join(", ");
    }
</script>

And here's the partial view I defined for the ContactGroupsEditor:

@model List<string>

@(Html.Kendo().MultiSelect()
    .Name("ContactGroups")
    .DataValueField("Text")
    .DataTextField("Text")
    .BindTo(new List<SelectListItem> 
    {
        new SelectListItem { Text = "GalacticEmpire"},
        new SelectListItem { Text = "RebelAlliance"}
    })
    .Value(Model)
)

This is very close to working the way I want it to. When I load into the page, the grid renders in the way I want it to, the Delete button works as expected, and the Edit button properly switches the Contact Groups column to the MultiSelect element. The issue I'm having is with the Create New Contact button. When I click that, I get a console error: Uncaught ReferenceError: ContactGroups is not defined. I suspect this is happening because when I create a new row, it's attempting to evaluate the JavaScript statement in the ClientTemplate statement in the grid, and failing because it hasn't been assigned a value yet. How can I correct this?


Solution

  • Add a default value for the ContactGroups property in the Model definition of the DataSource:

    model.Field(p => p.ContactGroup).DefaultValue(new List<string>());
    

    This way the ClientTemplate will be executed successfully.