Fixing bug in kendo grid row cancel, when inline editing is used.

I had a strange problem in Kendo grid, when a the last row was canceled the values of the first row were shown in the last row.

The first fix was adding a cancel even handler:

cancel: function (e) {
                     this.cancelChanges();
                 }

This fixed the bug, but introduced an other one.

Now rows would persist the canceled values.

To fix both problem I changed the event handler to:

cancel: function (e) {
      this.cancelChanges();
}

I used kendo 2017.1.118

How to validate an entered text to a min date in a kendo datepicker in AngularJS.

The code and live preview can be found here:

http://plnkr.co/edit/jdnRjO?p=preview

 

When no date is entered a “pink” border will be shown:

image

 

When a date is entered that’s before the “min” date a “pink” border will be shown:

 

image

 

When a date on or after the min date is entered, no border will be shown:

 

image

Setting height / width sparklines and removing spacing with Kendo UI and AngularJS

In the following screendump, I used 6 sparkline fields:

 

image

 

To increase the width / height of the sparkline (bar) I set the following values:

– charArea options (height, padding, margin)

– Series options (gap and spacing)

$scope.kostenMinderPersoneelChartOptions = {
chartArea: {
background: "",
height: 17,
margin: {
top: 1,
bottom: 0,
left: 0,
right: 0
},
padding: 0
},
tooltip: {
visible: false
},
series: [
{
type: 'bar',
color: '#EC008C',
field: 'sparkline',
gap: 0,
spacing: 0
}
],
valueAxis: {
min: 0,
max: 200000
}
};

Show hierarchy in combobox items, with Kendo and AngularJS.

Here is a plunkr showing a combobox with hierarchy:

http://plnkr.co/edit/PaiRPD6dZNq0JaT2Tkdg?p=preview

 

image

 

<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="spike">
<head>
<!--
This page can be used as a base for spiking with jQuery, AngularJS and Kendo.
All scripts and styles are loaded from a CDN or inline.
-->
<title>Spike page</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- Use highest support for modern standards . -->
<!-- Library styles -->
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.silver.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.silver.mobile.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.dataviz.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.dataviz.silver.min.css" rel="stylesheet" />
<!-- Library scripts -->
<script src="http://cdn.kendostatic.com/2014.2.1008/js/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.2.1008/js/angular.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.2.1008/js/kendo.all.min.js"></script>
<!-- App styles -->
<style>
/*
A small custom reset stylesheet is used, to fix style differences between browsers.
*/
html, body {
height: 100%; /* App layout uses a 100% height layout. */
}
body, div, p, ul, li {
border: 0; /* Remove unwanted space. */
-webkit-box-sizing: border-box; /* Place the border and padding inside the box. */
-moz-box-sizing: border-box; /* Place the border and padding inside the box. */
-ms-box-sizing: border-box; /* Place the border and padding inside the box. */
-o-box-sizing: border-box; /* Place the border and padding inside the box. */
box-sizing: border-box; /* Place the border and padding inside the box. */
margin: 0; /* Remove unwanted space. */
outline: 0; /* Remove unwanted space. */
padding: 0; /* Remove unwanted space. */
}
body {
padding: 20px; /* Create space between browser border and content. */
min-width: 320px; /* App will not work beneath width: 320px. */
}
.level1 {
}
.level2 {
padding-left: 30px;
}
</style>
<!-- App scripts -->
<script>
(function () {
"use strict";
// This is the starting point (main) for the angular app.
var app = angular.module("spike", ["kendo.directives"]);
}());
(function () {
"use strict";
var app = angular.module("spike");
var controller = function ($scope, service) {
$scope.title = "Show hierarchy in combobox items, with Kendo and AngularJS.";
$scope.countriesAndCities = [
{ "id": 1, "name": "The Netherlands", "level": 1 },
{ "id": 2, "name": "Amsterdam", "level": 2 },
{ "id": 3, "name": "Rotterdam", "level": 2 },
{ "id": 4, "name": "US", "level": 1 },
{ "id": 5, "name": "Las Vegas", "level": 2 },
{ "id": 6, "name": "New York", "level": 2 }
];
$scope.customTemplate = $("#customTemplate").html();
};
app.controller("main", ["$scope", controller]);
}());
</script>
</head>
<body>
<div ng-controller="main">
<h2>{{ title }}</h2>
<div>
<select kendo-combo-box
k-template="customTemplate"
k-placeholder="'Choose country'"
k-filter="contains"
k-data-source="countriesAndCities"
data-text-field="'name'"
data-value-field="'id'"
k-auto-bind="false"></select>
<script id="customTemplate" type="text/x-kendo-template">
<span class="k-state-default level#= level #">
#= name #
</span>
</script>
</div>
</div>
</body>
</html>

Using Kendo mobile switch with AngularJS and ng-model

 

Here’s a plunkr demonstrating, binding a kendo mobile switch

http://plnkr.co/edit/KlJ4JW?p=preview

image

 
 

<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="spike">
<head>
    <!–
        This page can be used as a base for spiking with jQuery, AngularJS and Kendo.
        All scripts and styles are loaded from a CDN or inline.
    –>
    <title>Spike page</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge"><!– Use highest support for modern standards . –>
    <!– Library styles –>
    <link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.common.min.css" rel="stylesheet" />
    <link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.silver.min.css" rel="stylesheet" />
    <link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.silver.mobile.min.css" rel="stylesheet" />
    <link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.dataviz.min.css" rel="stylesheet" />
    <link href="http://cdn.kendostatic.com/2014.2.1008/styles/kendo.dataviz.silver.min.css" rel="stylesheet" />

    <!– Library scripts –>
    <script src="http://cdn.kendostatic.com/2014.2.1008/js/jquery.min.js"></script>
    <script src="http://cdn.kendostatic.com/2014.2.1008/js/angular.min.js"></script>
    <script src="http://cdn.kendostatic.com/2014.2.1008/js/kendo.all.min.js"></script>

    <!– App styles –>
    <style>
        /*
            A small custom reset stylesheet is used, to fix style differences between browsers.
        */
        html, body {
            height: 100%; /* App layout uses a 100% height layout. */
        }

        body, div, p, ul, li {
            border: 0; /* Remove unwanted space. */
            -webkit-box-sizing: border-box; /* Place the border and padding inside the box. */
            -moz-box-sizing: border-box; /* Place the border and padding inside the box. */
            -ms-box-sizing: border-box; /* Place the border and padding inside the box. */
            -o-box-sizing: border-box; /* Place the border and padding inside the box. */
            box-sizing: border-box; /* Place the border and padding inside the box. */
            margin: 0; /* Remove unwanted space. */
            outline: 0; /* Remove unwanted space. */
            padding: 0; /* Remove unwanted space. */
        }

        body {
            padding: 20px; /* Create space between browser border and content. */
            min-width: 320px; /* App will not work beneath width: 320px. */
        }

        .km-switch {
            margin-top: 20px;
        }

        .km-switch, .km-checkbox, .km-switch-label-on, .km-switch-label-off {
            cursor: pointer;
        }
    </style>

    <!– App scripts –>
    <script>

        (function () {
            "use strict";

            // This is the starting point (main) for the angular app.
            var app = angular.module("spike", ["kendo.directives"]);
        }());

        (function () {
            "use strict";

            var app = angular.module("spike");

            var controller = function ($scope, service) {
                $scope.message = "The switch should show YES:";
                $scope.isChecked = true;
            };

            app.controller("MainController", ["$scope", controller]);
        }());
    </script>
</head>
<body>
    <div ng-controller="MainController">
        <div>{{ message }}</div>
        <div><input kendo-mobile-switch type="checkbox" k-on-label="’Yes’" k-off-label="’No’" k-ng-model="isChecked" value="{{ isChecked }}" /></div>
    </div>
</body>
</html>

 
 
 

AngularJS and Breeze – A simple crud app – Part 3 –Adding foreign keys and Kendo UI widgets.

 

Using Kendo UI mobile switch in AngularJS generated grid.

image

 

Using Kendo UI date picker in AngularJS generated grid.

image

 

Using Kendo UI combobox in AngularJS generated grid.

image

 

All code can be found at:

https://github.com/roelvanlisdonk/Research/tree/master/Research/Research.UI.Web/Client/Features/AngularJS_and_Breeze/Part3

 

Some highlights:

 

AngularJS directive

This directive will render the controls in the grid

spa.app.directive('ngField',['$compile', function ($compile) {
var directive = {
restrict: 'A', /* restrict this directive to elements */
link: function ($scope, element, attrs) {
var html = '<input ng-disabled="{{vm.isKeyField(prop)}}" type="text" ng-model="entity[prop.name]">';
if ($scope.prop.relatedNavigationProperty) {
var relatedTableName = $scope.prop.relatedNavigationProperty.nameOnServer;
html = '<select kendo-combo-box ng-model="entity[prop.name]" ng-options="record.id as record.firstName for record in vm[\'' + relatedTableName + '\']"></select>';
} else if ($scope.prop.dataType.name === "DateTime") {
html = '<input kendo-date-picker k-ng-model="entity[prop.name]" k-format="\'dd-MMM-yyyy\'" />';
} else if ($scope.prop.dataType.name === "Boolean")
{
html = '<input kendo-mobile-switch k-on-label="\'YES\'" k-off-label="\'NO\'" />';
}
var compiled = $compile(html)($scope);
element.replaceWith(compiled);
element = compiled;
}
};
return directive;
}]);

 

HTML

The HTML shows a splash page with the text “Loading data…” by using the ng-cloak AngularJS directive.

By putting all external resources, like “link” and “script” tags at the bottom of the page and inlining the minimal CSS to show the splash page, the splash page is immediately shown to the user, while the AngularJS app is booted and the data is loaded.

<!DOCTYPE html>
<html data-ng-app="app">
<head>
<title data-ng-bind="title">Angular and Breeze</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<!-- All external resources are moved to the bottom of the page, to allow direct rendering of the [splash screen]. -->
<!-- Only the styling for the [loader / splash screen] is included in the head. -->
<style type=text/css>
html, body {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; /* Border boxing is used, so the padding, margin and borders are within the width and height of the element. */
height: 100%;           /* Full screen single page app. */
margin: 0;              /* Prevent unnecessary white space. */
max-height: 100%;       /* Full screen single page app. */
outline: 0;             /* Prevent unnecessary white space. */
padding: 0;             /* Prevent unnecessary white space. */
}
body {
padding: 20px;
}
div.spa-splash {
display: none;
}
div.spa-splash, div.spa-splash > div {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; /* Border boxing is used, so the padding, margin and borders are within the width and height of the element. */
height: 100%;           /* Full screen single page app. */
max-height: 100%;       /* Full screen single page app. */
padding: 20px;            
}
div.spa-splash > div {
border: 1px solid rgb(212, 212, 212);
padding: 10px;
}
[ng-cloak].spa-splash {
display: block !important;
}
[ng-cloak] {
display: none;
}
</style>
</head>
<body>
<div class="spa-splash" ng-cloak><div>Loading data...</div></div>
<div class="spa-page container" data-ng-controller="admin as vm" ng-cloak>
<div class="spa-page-sidebar">
<div>Tables</div>
<div ng-repeat="entityType in vm.entityTypes"><a class="spa-action-link" ng-click="vm.refresh(entityType)">{{ entityType.shortName }}</a></div>
</div>
<div class="spa-page-content">
<div class="spa-grid-toolbar">
<a class="spa-action-link" ng-click="vm.save()">save</a> |
<a class="spa-action-link" ng-click="vm.reset()">reset</a> |
<a class="spa-action-link" ng-click="vm.create()">create</a>
<i class="fa fa-exclamation-circle"
title="Some data has change. Press save to save the changes to the server!"
ng-show="vm.isDirty"></i>
</div>
<table class="spa-grid">
<thead>
<tr>
<th> </th>
<th ng-repeat='(key, prop) in vm.entityDataFields'>{{ prop.name }}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="entity in vm.entities">
<td><a class="spa-action-link" ng-click="vm.delete(entity)">delete</a></td>
<td ng-repeat='(key, prop) in vm.entityDataFields'>
<div ng-field></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Libraries -->
<link rel="stylesheet" type="text/css" href="../../../Libraries/FontAwesome/css/font-awesome.min.css" />
<link rel="stylesheet" type="text/css" href="../../../Libraries/Toastr/toastr.min.css" />
<!-- App -->
<link rel="stylesheet" type="text/css" href="app.css" />
<!-- Libraries -->
<script type="text/javascript" src="../../../Libraries/jQuery/jquery-2.1.1.js"></script>
<script type="text/javascript" src="../../../Libraries/Angular/angular.js"></script>
<!-- Kendo -->
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.2.625/styles/kendo.common.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.2.625/styles/kendo.rtl.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.2.625/styles/kendo.metro.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.2.625/styles/kendo.metro.mobile.min.css" />
<script type="text/javascript" src="//cdn.kendostatic.com/2014.2.625/js/kendo.all.min.js"></script>
<!-- Breeze -->
<script type="text/javascript" src="../../../Libraries/Breeze/breeze.debug.js"></script>
<script type="text/javascript" src="../../../Libraries/Breeze/breeze.angular.js"></script>
<!-- Add toastr which needs jQuery (Breeze does not need jQuery). -->
<script type="text/javascript" src="../../../Libraries/Toastr/toastr.js"></script>
<script type="text/javascript" src="../../../Libraries/Moment/moment.js"></script>
<script type="text/javascript" src="../../../Libraries/Spin/spin.js"></script>
<!-- Add breeze.savequeuing which needs Q (Breeze does not need Q). -->
<script type="text/javascript" src="../../../Libraries/Q/q.min.js"></script>
<script type="text/javascript" src="../../../Libraries/Breeze/breeze.savequeuing.js"></script>
<!-- App -->
<script type="text/javascript" src="app.js"></script>
</body>
</html>

Controlling position of a custom confirm dialog with Kendo UI

The native confirm dialog, shown when you use the confirm function in JavaScript can’t be positioned in JavaScript.

A Kendo UI window can be positioned.

 

 

image

 

HTML

<!DOCTYPE html>
<html>
<head>
<title>Kendo element binding research page.</title>
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.common.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.rtl.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.metro.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.metro.mobile.min.css" />
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css">
<style>
/* Resets */
div, span, i, p, input, select {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; /* Border boxing is used, so the padding, margin and borders are within the width and height of de element. */
color: rgba(112, 112, 112, 1);
font-family: Arial, Helvetica, sans-serif; /* For know use default fonts used on google.com stackoverflow.com, telerik.com etc. */
font-size: 13px;
margin: 0; /* Margin zero is used to prevent unnecessary white space. */
padding: 0; /* Padding zero is used to prevent unnecessary white space. */
}        
html, body {
height: 100%;
max-height: 100%;
}
body {
padding: 20px;
}
.page {
border: 1px solid rgb(212, 212, 212);
height: 100%;
max-height: 100%;
padding: 10px;
position: relative;
}
#confirm > p {
padding-bottom: 20px;
}
.k-button {
cursor: pointer;
}
.k-window-titlebar, .k-window-titlebar > span {
cursor: move;
font-weight: bold;
}
</style>
</head>
<body>
<div class="page">
<button class="k-button" data-bind="click: onShowClick">Show confirm</button>
<div id="confirm"></div>
</div>
<script type="text/x-kendo-template" id="confirmTemplate">
<p>#= ConfirmText #</p>
<button class="k-button" id="yesButton">Yes</button>
<button class="k-button" id="noButton"> No</button>
</script>
<!-- Libraries -->
<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="//cdn.kendostatic.com/2014.1.528/js/kendo.all.min.js"></script>
<!-- Custom -->
<script type="text/javascript" src="app.js"></script>
</body>
</html>

 

Code

var kendo = kendo || {};
kendo.controller = (function () {
var self = {};
var _vm = null;
var _confirm = null;
var _confirmTemplate = null;
self.show = function () {
_confirm =  $("#confirm").kendoWindow({
title: "Delete record",
visible: false, // The window will not appear before its .open method is called.
width: "230px",
height: "100px",
}).data("kendoWindow");
_confirmTemplate = kendo.template($("#confirmTemplate").html());
_vm = new kendo.data.ObservableObject({
onShowClick: function () {
// Dynamically set some window options.
_confirm.setOptions({
position: {
top: 200,
left: 200
}
});
_confirm.content(_confirmTemplate({ ConfirmText: "Delete record?"}));
_confirm.open();
$("#yesButton").click(function () {
// TODO: Delete record.
_confirm.close();
})
$("#noButton").click(function () {
// User cancelled the window.
_confirm.close();
})
}
});
kendo.bind($(".page"), _vm);
};
return self;
})();
kendo.controller.show();

How to display a message, when a Kendo UI MVVM grid is empty.

If you want to show an text in a Kendo UI grid, you could use CSS, as suggested on stackoverflow.com:

http://stackoverflow.com/questions/23476978/display-a-message-within-the-kendo-grid-when-its-empty

 

But if you want to completely hide the gird and show a message, you can use a calculated field:

http://docs.telerik.com/kendo-ui/getting-started/framework/mvvm/observableobject#creating-dependent-methods-also-known-as-calculated-fields

 

image

 

HTML

<!DOCTYPE html>
<html>
<head>
<title>Kendo element binding research page.</title>
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.common.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.rtl.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.metro.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.metro.mobile.min.css" />
    <style>
/* Resets */
div, span, i, p, input, select {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; /* Border boxing is used, so the padding, margin and borders are within the width and height of de element. */
color: rgb(112, 112, 112);
font-family: Arial, Helvetica, sans-serif; /* For know use default fonts used on google.com stackoverflow.com, telerik.com etc. */
font-size: 13px;
margin: 0; /* Margin zero is used to prevent unnecessary white space. */
padding: 0; /* Padding zero is used to prevent unnecessary white space. */
}        
html, body {
height: 100%;
max-height: 100%;
}
body {
padding: 20px;
}
.info {
border: 1px solid rgb(128, 128, 128);
box-shadow: rgba(0, 0, 0, 0.298039) 0 2px 6px 0, rgba(0, 0, 0, 0.2) 0 -3px 8px 0;
padding: 10px;
}
.no-data {
border: 1px solid #dadada;
padding: 10px;
}
</style>
</head>
<body>
<div id="view">
<div class="info">            
<script id="productsRowTemplate" type="text/x-kendo-tmpl">
<tr data-uid="#: uid#">
<td>#: Id#</td>
<td>#: Name#</td>
</tr>
</script>
<div id="productsGrid" data-role="grid"
data-row-template="productsRowTemplate"
data-columns="[
{ 'field': 'Id' },
{ 'field': 'Name' }
]"
data-bind="source: products, invisible: productsIsEmpty"></div>
<div class="no-data" data-bind="visible: productsIsEmpty">No data.</div>
</div>
</div>
<!-- Libraries -->
<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="//cdn.kendostatic.com/2014.1.528/js/kendo.all.min.js"></script>

<!-- Custom -->
<script type="text/javascript" src="kendo-controller.js"></script>
</body>
</html>

 

JavaScript

var kendo = kendo || {};
kendo.controller = (function () {
var self = {};
var _vm = null;
self.show = function () {
_vm = new kendo.data.ObservableObject({
products: new kendo.data.DataSource({
data: new kendo.data.ObservableArray([
])
}),
productsIsEmpty: function () {
return this.get("products").data().length === 0;
}
});
kendo.bind($("#view"), _vm);
};
return self;
})();
kendo.controller.show();

Show kendo ui grid total record count with MVVM.

Kendo UI MVVM allows functions of objects to be called in the binding syntax:

<div class="totals"><span>Totals: </span><span data-bind="text: products.data().length"></span></div>

In this case the viewmodel property [products] is a kendo.data.DataSource object.

To get the total count of the records in the DataSource, you can use the function data().

This will return an ObservableArray which has a property length, containing the total record count.

 

image

 

HTML

<!DOCTYPE html> <html> <head> <title>Kendo element binding research page.</title> <link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.common.min.css" /> <link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.metro.min.css" /> <style> /* Resets */ div, span, i, p, input, select { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; /* Border boxing is used, so the padding, margin and borders are within the width and height of de element. */ color: rgb(112, 112, 112); font-family: Arial, Helvetica, sans-serif; /* For know use default fonts used on google.com stackoverflow.com, telerik.com etc. */ font-size: 13px; margin: 0; /* Margin zero is used to prevent unnecessary white space. */ padding: 0; /* Padding zero is used to prevent unnecessary white space. */ } html, body { height: 100%; max-height: 100%; } body { padding: 20px; } .info { border: 1px solid rgb(128, 128, 128); box-shadow: rgba(0, 0, 0, 0.298039) 0 2px 6px 0, rgba(0, 0, 0, 0.2) 0 -3px 8px 0; padding: 10px; } .totals { margin-top: 20px; font-weight: bold; } </style> </head> <body> <div id="view"> <div class="info"> <script id="productsRowTemplate" type="text/x-kendo-tmpl"> <tr data-uid="#: uid#"> <td>#: Id#</td> <td>#: Name#</td> </tr> </script> <div id="productsGrid" data-role="grid" data-row-template="productsRowTemplate" data-columns="[ { 'field': 'Id' }, { 'field': 'Name' } ]" data-bind="source: products"></div> <div class="totals"><span>Totals: </span><span data-bind="text: products.data().length"></span></div> </div> </div> <!-- Libraries --> <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.min.js"></script> <script type="text/javascript" src="//cdn.kendostatic.com/2014.1.528/js/kendo.all.min.js"></script>


<!-- Custom -->
<script type="text/javascript" src="kendo-controller.js"></script> </body> </html>

 

JavaScript (kendo-controller.js)

var kendo = kendo || {};
kendo.controller = (function () {
var self = {};
var _vm = null;
self.show = function () {
_vm = new kendo.data.ObservableObject({
products: new kendo.data.DataSource({
data: new kendo.data.ObservableArray([
{ Id: 1, Name: "Product 1" },
{ Id: 2, Name: "Product 2" },
{ Id: 3, Name: "Product 3" },
{ Id: 4, Name: "Product 4" },
{ Id: 5, Name: "Product 5" }
])
})
});
kendo.bind($("#view"), _vm);
};
return self;
})();
kendo.controller.show();

Using drag and drop to order rows in a Kendo UI grid

 

Before drag and drop

image

During drag and drop

image

 

After drag and drop

image

 

Code

<!DOCTYPE html>
<html>
<head>
<title>Kendo element binding research page.</title>
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.common.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.rtl.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.metro.min.css" />
<link rel="stylesheet" type="text/css" href="//cdn.kendostatic.com/2014.1.528/styles/kendo.metro.mobile.min.css" />
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css">
<style>
/* Resets */
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; /* Border boxing is used, so the padding, margin and borders are within the width and height of de element. */
color: rgb(112, 112, 112);
font-family: Arial, Helvetica, sans-serif; /* For know use default fonts used on google.com stackoverflow.com, telerik.com etc. */
font-size: 13px;
margin: 0; /* Margin zero is used to prevent unnecessary white space. */
padding: 0; /* Padding zero is used to prevent unnecessary white space. */
}
html, body {
height: 100%;
max-height: 100%;
}
body {
padding: 20px;
}
.info {
border: 1px solid rgb(128, 128, 128);
box-shadow: rgba(0, 0, 0, 0.298039) 0 2px 6px 0, rgba(0, 0, 0, 0.2) 0 -3px 8px 0;
padding: 10px;
}
.addressRow {
cursor: move;
cursor: -webkit-grab;
cursor: -moz-grab;
height: 10px;
line-height: 10px;
padding: 0;
margin: 0;
}
.addressRow input {
font-family: FontAwesome;
}
#addressGrid tr > td {
height: 1.6em;
line-height: 1.6em;
padding: 1px 4px 1px 4px;
margin: 0;
}
#addressGrid tr > th {
font-weight: bold;
height: 1.6em;
line-height: 1.6em;
margin: 0;
padding: 1px 4px 1px 4px;
}
#addressGrid tr > td:first-child, #addressGrid tr > th:first-child {
width: 56px;
}
#addressGrid tr:last-child td {
padding-bottom: 3px;
}
.km-switch {
cursor: pointer;
height: 1.6em;
line-height: 1.6em;
margin: 0;
padding: 0;
}
#addressGrid tr > td:first-child .km-switch-label-on, #addressGrid tr > td:first-child .km-switch-label-off {
font-family: FontAwesome;
color: rgb(112, 112, 112);
height: 1.6em;
line-height: 1.6em;
}
#addressGrid tr > td:first-child .km-switch-label-on:before {
content: "\f023";
}
#addressGrid tr > td:first-child .km-switch-label-off:before {
content: "\f09c";
}
</style>
</head>
<body>
<div id="view">
<div class="info">
<script id="addressRowTemplate" type="text/x-kendo-tmpl">
<tr data-uid="#: uid#" class="addressRow">
<td>
<input data-role="switch" data-on-label="" data-off-label="" data-bind="checked: IsFixed">
</td>
<td>
#: Address#
</td>
<td>
#: Lat#
</td>
<td>
#: Long#
</td>
<td>
<input data-role="switch" data-on-label="Y" data-off-label="N" data-bind="checked: IsFixed">
</td>
</tr>
</script>
<div id="addressGrid" data-role="grid"
data-row-template="addressRowTemplate"
data-columns="[
{ 'field': 'IsFixed' },
{ 'field': 'Address' },
{ 'field': 'Lat' },
{ 'field': 'Long' },
{ 'field': 'Selected' }
]"
data-bind="source: addresses"></div>
</div>
</div>
<script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="//cdn.kendostatic.com/2014.1.528/js/kendo.all.min.js"></script>
<script type="text/javascript" src="/Client/Libraries/Live/head.min.js"></script>
<script type="text/javascript" src="/Client/Libraries/Live/live.js"></script>
<script type="text/javascript">
kendo.addDragAndDropToGrid = function (gridId, rowClass, viewModel, validateDropTargetFunc)
{
if (!gridId) { throw "Parameter [gridId] is not set."; }
if (!rowClass) { throw "Parameter [rowClass] is not set."; }
$(rowClass).kendoDraggable({
hint: function (element)
{
return element.clone();
}
});
$(gridId).kendoDropTargetArea({
filter: rowClass,
drop: function (e)
{
var srcUid = e.draggable.element.data("uid");
var dstUid = e.dropTarget.data("uid");
var ds = $(gridId).data("kendoGrid").dataSource;
var srcItem = ds.getByUid(srcUid);
var dstItem = ds.getByUid(dstUid);
var dstIdx = ds.indexOf(dstItem);
ds.remove(srcItem);
ds.insert(dstIdx, srcItem);
e.draggable.destroy();
kendo.addDragAndDropToGrid(gridId, rowClass, viewModel, validateDropTargetFunc);
}
});
};
var dataService = (function ()
{
"use strict";
var self = {};
self.getAddresses = function ()
{
var data = new kendo.data.ObservableArray(
[
{ Id: 1, Address: 'Kerkweg 22',   Lat: '52.367443', Long: '4.865275', Selected: false, IsFixed: false },
{ Id: 2, Address: 'Peilstraat 3', Lat: '52.367967', Long: '4.866217', Selected: false, IsFixed: true },
{ Id: 3, Address: 'Bakkerloop 35', Lat: '52.367946', Long: '4.865482', Selected: false, IsFixed: false },
{ Id: 4, Address: 'Eikenlaan 1', Lat: '52.368237', Long: '4.866694', Selected: false, IsFixed: true }
]);
// Manual create a promise, so this function mimicks an Ajax call.
var dfd = new $.Deferred();
dfd.resolve(data);
return dfd.promise();
};
return self;
})(kendo);
var viewModel = new kendo.observable({
addresses: new kendo.data.DataSource({ data: [] })
});
var controller = (function (dataService, viewModel)
{
"use strict";
var _dataService = dataService;            
var _vm = viewModel;
var self = {};
self.handleAdressesRefresh = function (data)
{
_vm.set("addresses", new kendo.data.DataSource({ data: data }));
kendo.bind($(".info"), _vm);
kendo.addDragAndDropToGrid("#addressGrid", ".addressRow", _vm);
};
self.show = function ()
{
$.when(_dataService.getAddresses())
.then(self.handleAdressesRefresh);
};
return self;
})(dataService, viewModel);
controller.show();
</script>
</body>
</html>