0
votes

The title may be confusing, but I had a bit of trouble explaining myself in a single sentence, so read on for a bit more detailed scenario.

I am trying to get a Kendo UI DropDownList working correctly when used as an editor in a Kendo UI Grid.

I've got the following @model in my view;

{
  "DataItems": [
    { "Id": 1, "Name": "Foo", "Category": { "Id": 1 } },
    { "Id": 2, "Name": "Bar", "Category": { "Id": 2 } }
  ],
  "CategoryOptions": [
    { "Id": 1, "Name": "A" },
    { "Id": 2, "Name": "B" },
    { "Id": 3, "Name": "C" }
  ],
}

This is passed to my script, which upon initializing constructs the following data source and grid

var gridDataSource = new kendo.data.DataSource({
    data: _model.DataItems,
    schema: {
        model: {
            id: "Id",
            fields: {
                Id: { type: "number", editable: false, nullable: false },
                Name: { type: "string", validation: { required: true } },
                Category: { type: "object" },
            }
        },
    }
});
$("#grid").kendoGrid({
    dataSource: _model.DataItems,
    columns: [
        { field: "Id", hidden: true },
        { field: "Name", width: "200px", title: "Name", },
        { field: "Category", title: "Category", editor: categoryDropDownList, template: "#= (Category != null && Category.Name !== null) ? Category.Name : ' ' #" },
        { command: "destroy", title: " "}
    ],
    toolbar: ["save", "cancel"],
    editable: true,
});

As you'll notice this grid is in-line editable, so clicking a cell will allow you to edit its contents. To edit Category I've added a custom editor (categoryDropDownList), which displays _model.CategoryOptions.

function categoryDropDownList(container, options) {
    $('<input data-value-field="Id" data-text-field="Name" data-bind="value:' + options.field + '"/>').appendTo(container)
        .kendoDropDownList({
            dataSource: _model.CategoryOptions,
            dataValueField: "Id",
            dataTextField: "Name",
        });
}

This seems to work as expected.

You can click the Category cell, and select a value (A, B, or C). When you remove focus from that cell, a small flag appear in the top left corner to mark that cell as dirty, requiring you to save changes.

In my model the data item Bar has the category B. This means that upon loading the page, one would expect the cell value of Category to be B, as dictated by the template;

#= (Category != null && Category.Name !== null) ? Category.Name : ' ' #

Instead the text value in the Category cell is always empty, as if you hit the else of the ternary if template, which shouldn't be the case. It should be B.

However, if you click the cell to reveal the editor, you'll notice that the selected item in the DropDownList is actually B. Remove focus from the cell, and the value disappears with the DropDownList.

So it's as if the editor knows about the selected category, but the grid doesn't.

Does this make any sense for you guys?

Please leave a comment if you need a better explanation, more code etc.

1

1 Answers

1
votes

It's most likely because the editor template is asking for Category.Name, but it is null. The Category object in DataItems only has Id defined and has no idea that there is a relationship defined at CategoryOptions.

In your editor template, you can try something like this (or similar).

#= (Category.Id !== null) ? $.grep(CategoryOptions, function(e){ return e.Id == Category.Id; })[0].Name : ' ' #

Basically, return the Name of the object in CategoryOptions with an Id that matches the Category Id of DataItem.


If trying that does not work, you can try the column.values configuration that kendo supports. I imagine it would look something like this:

Your category column (no more template):

{ 
  field: "Category", 
  title: "Category", 
  editor: categoryDropDownList, 
  values: CategoryOptions      
},

Your data model would then need to be like this:

{
   "DataItems": [
       { "Id": 1, "Name": "Foo", "Category": 1 },
       { "Id": 2, "Name": "Bar", "Category": 2 }
   ],
   "CategoryOptions": [
       { "value": 1, "text": "A" },
       { "value": 2, "text": "B" },
       { "value": 3, "text": "C" }
   ],
}

Adding function to kendo template context

Declare your wrapper function inline as part of the editor template:

"# var GetCategoryNameById = function(id){ return $.grep(CategoryOptions, function(e){ return e.Id == id; })[0].Name; }; # #= GetCategoryNameById(name) #"

Kendo Template Hash Usage FYI:

#= # --> Render as HTML

# # --> Arbitrary JS