KendoUI MultiSelect in a Grid: Yes, we can!


In Spring 2013 (see Release Note) KendoUI introduced a new widget: MultiSelect. Similar to a Drop Down List but this time you see all selected options as some sort of buttons with an (x) for deleting it and a Drop Down List for adding new items.

Kendo UI MultiSelect widget
Kendo UI MultiSelect widget

But as well as it happens with dates or booleans, you do not have a Kendo UI out-of-the-box support of input fields of this type, in a Kendo UI Grid. If you want to use a MultiSelect, DatePicker, AutoComplete, CheckBox,… you need to write and editor function.

KendoUI: MultiSelect

Using MultiSelect widget for an input field is pretty simple, you just need to define an HTML select and invoke the kendoMultiSelect initialization with little more than a DataSource that is an array of valid options.

<select id="select"></select>
$("#select").kendoMultiSelect({
    dataSource: [
        "Africa",
        "Europe",
        "Asia",
        "North America",
        "South America",
        "Antarctica",
        "Australia"
    ]
});

And if we display what it stores, we can see that is is an array of strings.

KendoUI MultiSelect value
KendoUI MultiSelect value

 

KendoUI: MultiSelect, saving ids

But in the previous case the DataSource is just an array of strings but you might have both text: what you want to show; and value what you want to store. You configure which field is used for text in dataTextField and which for value with dataValueField

If so, you define the DataSource as:

$("#select").kendoMultiSelect({
    dataTextField : "text",
    dataValueField: "id",
    dataSource    : [
        { text: "Africa", id: 1 },
        { text: "Europe", id: 2 },
        { text: "Asia", id: 3 },
        { text: "North America", id: 4 },
        { text: "South America", id: 5 },
        { text: "Antarctica", id: 6 },
        { text: "Australia", id: 7 }
    ]
});

Now, when we display the values, we get:

KendoUI MultiSelect values when explicitly set text and value fields.
KendoUI MultiSelect values when explicitly set text and value fields.

 

KendoUI Grid with MultiSelect field

Now, it is time for using this MultiSelect in a Grid with the considerations above.

KendoUI Grid displaying MultiSelect cell

1. We have seen that values are stored in an array in KendoUI MultiSelect, so we cannot directly show them in a Grid cell or it will be displayed as an array.

Kendo UI MultiSelect value displayed  in a Grid cell
Kendo UI MultiSelect value displayed in a Grid cell

2. This is actually easy to solve, we use a template in the column definition that serialize MultiSelect value to a string separated by commas using join method.

columns   : [
    ...
    { field: "Cities", width: 300, template: "#= Cities.join(', ') #" }
]
Kendo UI MultiSelect value displayed  in a Grid cell separated by commas
Kendo UI MultiSelect value displayed in a Grid cell separated by commas

 

KendoUI Grid editing MultiSelect cell

Now, we have to inform KendoUI Grid how we want a multi-value cell to be edited: edit using a MultiSelect; and we do this using editor attribute in the column definition.

columns   : [
    ...
    { field: "Cities", width: 300, template: "#= Cities.join(', ') #", editor: citiesEditor }
]

The only remaining thing is define citiesEditor that is pretty simple:

function citiesEditor(container, options) {
    $("<select multiple='multiple' data-bind='value : Cities'/>")
            .appendTo(container)
            .kendoMultiSelect({
                dataSource: CitiesDS
            });
}

Generate an HTML select with option multiple and bind it to field Cities doing data-bind=’value : Cities’. Now our Grid while editing the list of Cities looks like:

KendoUI MultiSelect value formatted using template
KendoUI MultiSelect value formatted using template

So, it turned out not to be so difficult. Although that is still pending the case when we want to save the id instead of the text. This will be covered in the second part of this post.

KendoUI: readonly rows (how to and command template)


A couple days ago Piyush, a frequent reader and commenter on this blog, asked me about how to make a row in a KendoUI grid read-only.

What he tried was handling edit event and if the row was read-only then he exited the edit mode but this introduced and undesired effect: a flickering (due to entering and exiting edit popup/inline mode).

KendoUI: read-only rows

Flickering

What Piyush originally asked me was how to avoid flickering but this is actually not possible since by the time edit event is fired, the row is already in edit mode.

You can easily demonstrate this introducing and alert(“editing”); in the code and you see that the popup window for editing fields is active while alert window is waiting for ok so, you will always have the flickering.

Lets have the following DataSource definition:

var dataSource = new kendo.data.DataSource({
    data    : [
        { symbol: "AAPL", company: "Apple Inc.", readonly: true },
        { symbol: "AMZN", company: "Amazon.com Inc.", readonly: true },
        { symbol: "IBM", company: "International Business Machines Corp." },
        { symbol: "CSCO", company: "Amazon.com Inc", readonly: true },
        { symbol: "MSFT", company: "Microsoft Corp.", readonly:false },
        { symbol: "INTC", company: "Intel Corp." },
        { symbol: "QCOM", company: "QUALCOMM Inc." },
        { symbol: "ORCL", company: "Oracle Corp." },
        { symbol: "HPQ", company: "Hewlett-Packard Company" },
        { symbol: "CRM", company: "salesforce.com, Inc." }
    ],
    pageSize: 5
});

And the grid defined as:

var grid = $("#stocks_tbl").kendoGrid({
    dataSource: dataSource,
    columns   : [
        { command: "edit", width: 100 },
        { field: "symbol", title: "Symbol", width: 100 },
        { field: "company", title: "Company", width: 300 }
    ],
    editable  : "popup",
    edit      : function () {
        alert("editing");
        grid.closeCell();
    },
    pageable  : true
}).data("kendoGrid");

If you run this you will see:

Capture1

So, there is nothing that we can do for avoiding the flickering but there are some things that I can do for getting the desired result.

Template based solution

This solution is based on defining a template that creates an Edit button for each row but controlled by readonly field.

The template would be something like:

<script id="edit-template" type="text/x-kendo-template">
    # if (!data.readonly) { #
    <a class="k-button k-button-icontext k-grid-edit" href="\#"><span class="k-icon k-edit"></span>Edit</a>
    # } #
</script>

and the new JavaScript code:

var editTemplate = kendo.template($("#edit-template").html());
var grid = $("#stocks_tbl").kendoGrid({
    dataSource: dataSource,
    columns   : [
        { field: "readonly", title: "", width: 100, template: editTemplate },
        { field: "symbol", title: "Symbol", width: 100 },
        { field: "company", title: "Company", width: 300 }
    ],
    editable  : "popup",
    pageable  : true
}).data("kendoGrid");

And this looks like:

Capture2

Done! … Actually almost, if I click on Edit button, I get:

Capture3

Where the field readonly is editable.

I might try to define a Schema for the DataSource and define readonly as not editable. But this does not prevent the field from being rendered.

Capture4

What else may I try?

  1. Remove the title of the field by defining it to a white-space using title: “ “ (note that there is a blank between both “).
  2. Define an editor function that actually does nothing.

What I have now is:

var grid = $("#stocks_tbl").kendoGrid({
    dataSource: dataSource,
    columns   : [
        { field: "readonly", title: " ", width: 100, template: editTemplate, editor: function() {} },
        { field: "symbol", title: "Symbol", width: 100 },
        { field: "company", title: "Company", width: 300 }
    ],
    editable  : "popup",
    pageable  : true
}).data("kendoGrid");

And when I edit the field I finally get:

Screen Shot 2012-12-26 at 00.43.28

KendoUI: Sortable Widget


My friend kept challenging me about jQuery UI Sortable and my implementation of KendoUI Sortable Lists. He asked me to go a step further and implement a Sortable Grid that would allow to move cells in horizontal and vertical.

KendoUI Sortable Grid

KendoUI Sortable Grid: See it in action

I think that the very best is see what it can do:

But, it does not actually to be a regular grid (all cell with the same width):

Not even just static content elements, they might be other KendoUI widgets:

KendoUI Sortable Grid: Description

Basically you define an HTML element that contains group of HTML elements (rows). Each row contains a list of HTML elements (cells).

So, this widget is able to:

  • Move a cells inside a row or between rows.
  • If a row gets empty (no cells on it after a move), then the row is removed.
  • If you drop a cell in the space between rows (in the videos it has been styled as box in slightly darker border), then a new row is inserted with the element being dragged.