New to Kendo UI for jQuery? Download free 30-day trial

Grid Integration

You can use the Kendo UI Sortable component to reorder the items in a Grid by dragging and dropping.

Prerequisites

Reordering of Sortable Items

The Sortable reorders the HTML DOM elements. It does not automatically update the order of the items in the DataSource. This means that you have to explicitly implement the desired behavior.

Reordering of Grid Table Rows

To reorder the table rows of the Grid, initialize the Sortable on the table element of the Grid. Normally, the filter property of the Sortable selects all tr elements that are direct children of the table tbody element, for example, filter: ">tbody >tr".

In AngularJS applications, initialize the Sortable as a parent directive. The filter configuration option selects all tr elements that are children of the .k-grid wrapper.

Setting the Hint in the Grid

The hint element of the Sortable is appended to the <body> element. As a result, its width is different from the width of the Grid.

The following example demonstrates how to style the hint element, so it looks like the row element that is currently dragged.

<div id="grid"></div>
<script>

  $("#grid").kendoGrid({
    dataSource: {
      data: [{name: "John", age: 25}, {name: "Jane", age: 25}]
    }
  });

  $("#grid").data("kendoGrid").table.kendoSortable({
    filter: ">tbody >tr",
    hint: function(element) { // Customize the hint.
      var grid = $("#grid").data("kendoGrid"),
          table = grid.table.clone(), // Clone the Grid table.
          wrapperWidth = grid.wrapper.width(), // Get the Grid width.
          wrapper = $("<div class='k-grid k-widget'></div>").width(wrapperWidth),
          hint;

      table.find("thead").remove(); // Remove the Grid header from the hint.
      table.find("tbody").empty(); // Remove the existing rows from the hint.
      table.wrap(wrapper); //wrap the table
      table.append(element.clone()); // Append the dragged element.

      hint = table.parent(); // Get the wrapper.

      return hint; // Return the hint element.
    },
    placeholder: function(element) { // Customize the placeholder.
      return element.clone().addClass("k-hover").css("opacity", 0.65);
    },
    change: function(e) {
      // Handle the change event.
      // Update the underlying data according to the DOM position change.
      // See the previous examples.
    }
  });
</script>

Reordering in Editable Grids

If the editing functionality of the Grid is enabled, use a more specific filter selector that excludes the item, which is currently in edit mode, for example, .filter(">tbody >tr:not(.k-grid-edit-row)"). In this way, the Sortable functionality will not interfere with the editing feature of the Grid.

If the Grid is configured to display details, use a selector that matches only the master Grid rows, for example, filter: ">tbody >tr.k-master-row". In this way, the detail rows will not be draggable.

For more information on the Sortable events, refer to the JavaScript API article on Sortable events and the demo on integrating the Sortable and the Grid.

The editing functionality of the Kendo UI Grid is rendered through its inline, popup, or batch edit mode. The inline and popup modes are more common and easier to implement than the batch edit mode.

Using Grids in Inline and Popup Edit Modes

If you use the inline or the popup edit mode, set a more specific filter which excludes the item that is currently in edit mode.

.filter(">tbody >tr:not(.k-grid-edit-row)")

Using Grids in Batch Edit Mode

The draggable functionality of the Sortable prevents the mousedown event. As a result, the change event of the editor input does not fire, which in turn prevents the MVVM from saving the updated value.

If you use the batch (incell) edit mode, the code from the previous example that is applied to the inline and popup edit modes will not work. To work around this issue, use custom editors and configure them to update when the input event fires—by default, the framework listens for the change event. To implement the solution, add the data-value-update="input" attribute to the editor inputs. The downside of this approach is that the input event does not work for earlier Internet Explorer versions.

The data-value-update approach works with regular inputs. However, you must manually configure the Kendo UI components as they do not support the data-value-update attribute.

For a runnable example, refer to the article on using the Sortable with Grids in incell edit mode.

Reordering of DataSource Items

The change event of the Sortable component will fire after a row position is changed. You can bind to the change event to update the order of the items in the DataSource.

The following example demonstrates how to shift the position of the items in the DataSource.

// The change event handler of the Sortable.
function onChange(e) {
    var grid = e.sender.element.data("kendoGrid"),
        oldIndex = e.oldIndex , //the old position
        newIndex = e.newIndex , //the new position
        view = grid.dataSource.view(),
        dataItem = grid.dataSource.getByUid(e.item.data("uid")); //retrieve the moved dataItem

    dataItem.Order = newIndex; //update the order
    dataItem.dirty = true;

    // Shift the order of the records.
    if (oldIndex < newIndex) {
        for (var i = oldIndex + 1; i <= newIndex; i++) {
            view[i].Order--;
            view[i].dirty = true;
        }
    } else {
        for (var i = oldIndex - 1; i >= newIndex; i--) {
            view[i].Order++;
            view[i].dirty = true;
        }
    }

    grid.dataSource.sync(); // Submit the changes through the update transport and refresh the Grid.
}

The following example demonstrates how to send the newIndex and oldIndex to the server.

// The change event handler of the Sortable.
function onChange(e) {
    var grid = e.sender.element.data("kendoGrid"),
        oldIndex = e.oldIndex , // The old position.
        newIndex = e.newIndex , // The new position.
        dataItem = grid.dataSource.getByUid(e.item.data("uid")); // Retrieve the moved dataItem.

    $.ajax({
        url: "yourUrl",
        dataType: "json",
        data: { // Send the data and update the order of the items on the server.
            oldIndex: oldIndex,
            newIndex: newIndex,
            dataItem: dataItem
        },
        success: function (response) {
            grid.dataSource.read(); // Refresh the Grid.
        }
    });
}

Known Limitations

  • The Sortable does not work as expected with a Grid that has its paging or virtual scrolling enabled.

    The Sortable operates with the existing DOM. It is not aware of the Grid or of its DataSource. If paging or virtual scrolling are enabled, the Grid will render only the elements which belong to the current page. As a result, the sorting will be limited to the current page only.

  • The Sortable does not work as expected with a grouped Grid.

    The Sortable uses the index of the DOM elements. When the Grid displays grouped data, the index of the DOM element does not match the index of the corresponding data item in the DataSource. This makes updating the order in the DataSource impossible.

  • The Sortable does not work with a Grid that has locked (frozen) columns.

See Also

In this article