Last Row Warning Message Issue In Kendo Grid

Introduction

Usually, while using validation in Kendo Grid, you will find some design issues in the Grid when displaying the warning/error message. This blog will tell you how to fix this issue..

Kendo Grid with validation

I will implement the Kendo Grid by referring http://demos.telerik.com/kendo-ui/grid/editing 

KendoGrid.html

  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.   <meta charset="utf-8">  
  5.   <title>Untitled</title>  
  6.   
  7.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.common.min.css">  
  8.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.rtl.min.css">  
  9.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.default.min.css">  
  10.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.mobile.all.min.css">  
  11.   
  12.   <script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>  
  13.   <script src="http://kendo.cdn.telerik.com/2017.1.118/js/angular.min.js"></script>  
  14.   <script src="http://kendo.cdn.telerik.com/2017.1.118/js/jszip.min.js"></script>  
  15.   <script src="http://kendo.cdn.telerik.com/2017.1.118/js/kendo.all.min.js"></script></head>  
  16. <body>  
  17.    <div id="example">  
  18.             <div id="grid"></div>  
  19.   
  20.             <script>  
  21.                 $(document).ready(function () {  
  22.          
  23.   
  24.                     var crudServiceBaseUrl = "https://demos.telerik.com/kendo-ui/service",  
  25.                         dataSource = new kendo.data.DataSource({  
  26.                             transport: {  
  27.                                 read:  {  
  28.                                     url: crudServiceBaseUrl + "/Products",  
  29.                                     dataType: "jsonp"  
  30.                                 },  
  31.                                 update: {  
  32.                                     url: crudServiceBaseUrl + "/Products/Update",  
  33.                                     dataType: "jsonp"  
  34.                                 },  
  35.                                 destroy: {  
  36.                                     url: crudServiceBaseUrl + "/Products/Destroy",  
  37.                                     dataType: "jsonp"  
  38.                                 },  
  39.                                 create: {  
  40.                                     url: crudServiceBaseUrl + "/Products/Create",  
  41.                                     dataType: "jsonp"  
  42.                                 },  
  43.                                 parameterMap: function(options, operation) {  
  44.                                     if (operation !== "read" && options.models) {  
  45.                                         return {models: kendo.stringify(options.models)};  
  46.                                     }  
  47.                                 }  
  48.                             },  
  49.                             batch: true,  
  50.                             pageSize: 20,  
  51.                             schema: {  
  52.                                 model: {  
  53.                                     id: "ProductID",  
  54.                                     fields: {  
  55.                                         ProductID: { editable: false, nullable: true },  
  56.                                         ProductName: { validation: { required: true } },  
  57.                                         UnitPrice: { type: "number", validation: { required: true, min: 1} },  
  58.                                         Discontinued: { type: "boolean" },  
  59.                                         UnitsInStock: { type: "number", validation: { min: 0, required: true } }  
  60.                                     }  
  61.                                 }  
  62.                             }  
  63.                         });  
  64.   
  65.                     $("#grid").kendoGrid({  
  66.                         dataSource: dataSource,  
  67.                         navigatable: true,  
  68.                         pageable: true,  
  69.                         height: 550,  
  70.                         toolbar: ["create""save""cancel"],  
  71.                         columns: [  
  72.                             "ProductName",  
  73.                             { field: "UnitPrice", title: "Unit Price", format: "{0:c}", width: 120 },  
  74.                             { field: "UnitsInStock", title: "Units In Stock", width: 120 },  
  75.                             { field: "Discontinued", width: 120 },  
  76.                             { command: "destroy", title: " ", width: 150 }],  
  77.                         editable: true  
  78.                     });  
  79.                 });  
  80.             </script>  
  81.         </div>  
  82. </body>  
  83. </html>   

Result in browser 

 
From the above figure, you can notice there is a break in error message. In the last row of Grid, the user needs to scroll down manually to check the error message. This is somewhat odd from a user's perspective. Let’s see how to fix it with simple logic which is written in the below function.
  1.          $(function () {  
  2.     var grid = $("#grid").data("kendoGrid");  
  3.   
  4.     grid.table.on("focusout"".k-invalid"function () {  
  5.         var content = grid.content;  
  6.         var height = content.height();  
  7.         var cell = $(this).closest("td");  
  8.         var message = cell.find(".k-invalid-msg");  
  9.         var callout = message.find(".k-callout");  
  10.         var position = message.position();  
  11.         var top = position.top + callout.outerHeight() + message.outerHeight();  
  12.         if (top > height) {  
  13.             content.scrollTop(content.scrollTop() + top - height);  
  14.         }  
  15.     });  
  16. });  
Complete code
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.   <meta charset="utf-8">  
  5.   <title>Untitled</title>  
  6.   
  7.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.common.min.css">  
  8.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.rtl.min.css">  
  9.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.default.min.css">  
  10.   <link rel="stylesheet" href="http://kendo.cdn.telerik.com/2017.1.118/styles/kendo.mobile.all.min.css">  
  11.   
  12.   <script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>  
  13.   <script src="http://kendo.cdn.telerik.com/2017.1.118/js/angular.min.js"></script>  
  14.   <script src="http://kendo.cdn.telerik.com/2017.1.118/js/jszip.min.js"></script>  
  15.   <script src="http://kendo.cdn.telerik.com/2017.1.118/js/kendo.all.min.js"></script></head>  
  16. <body>  
  17.    <div id="example">  
  18.             <div id="grid"></div>  
  19.   
  20.             <script>  
  21.                 $(document).ready(function () {  
  22.          
  23.              $(function () {  
  24.                 var grid = $("#grid").data("kendoGrid");  
  25.   
  26.                 grid.table.on("focusout"".k-invalid"function () {  
  27.                 var content = grid.content;  
  28.                 var height = content.height();  
  29.                 var cell = $(this).closest("td");  
  30.                 var message = cell.find(".k-invalid-msg");  
  31.                 var callout = message.find(".k-callout");  
  32.                 var position = message.position();  
  33.                 var top = position.top + callout.outerHeight() + message.outerHeight();  
  34.                 if (top > height) {  
  35.                 content.scrollTop(content.scrollTop() + top - height);  
  36.             }  
  37.         });  
  38.     });  
  39.   
  40.                     var crudServiceBaseUrl = "https://demos.telerik.com/kendo-ui/service",  
  41.                         dataSource = new kendo.data.DataSource({  
  42.                             transport: {  
  43.                                 read:  {  
  44.                                     url: crudServiceBaseUrl + "/Products",  
  45.                                     dataType: "jsonp"  
  46.                                 },  
  47.                                 update: {  
  48.                                     url: crudServiceBaseUrl + "/Products/Update",  
  49.                                     dataType: "jsonp"  
  50.                                 },  
  51.                                 destroy: {  
  52.                                     url: crudServiceBaseUrl + "/Products/Destroy",  
  53.                                     dataType: "jsonp"  
  54.                                 },  
  55.                                 create: {  
  56.                                     url: crudServiceBaseUrl + "/Products/Create",  
  57.                                     dataType: "jsonp"  
  58.                                 },  
  59.                                 parameterMap: function(options, operation) {  
  60.                                     if (operation !== "read" && options.models) {  
  61.                                         return {models: kendo.stringify(options.models)};  
  62.                                     }  
  63.                                 }  
  64.                             },  
  65.                             batch: true,  
  66.                             pageSize: 20,  
  67.                             schema: {  
  68.                                 model: {  
  69.                                     id: "ProductID",  
  70.                                     fields: {  
  71.                                         ProductID: { editable: false, nullable: true },  
  72.                                         ProductName: { validation: { required: true } },  
  73.                                         UnitPrice: { type: "number", validation: { required: true, min: 1} },  
  74.                                         Discontinued: { type: "boolean" },  
  75.                                         UnitsInStock: { type: "number", validation: { min: 0, required: true } }  
  76.                                     }  
  77.                                 }  
  78.                             }  
  79.                         });  
  80.   
  81.                     $("#grid").kendoGrid({  
  82.                         dataSource: dataSource,  
  83.                         navigatable: true,  
  84.                         pageable: true,  
  85.                         height: 550,  
  86.                         toolbar: ["create""save""cancel"],  
  87.                         columns: [  
  88.                             "ProductName",  
  89.                             { field: "UnitPrice", title: "Unit Price", format: "{0:c}", width: 120 },  
  90.                             { field: "UnitsInStock", title: "Units In Stock", width: 120 },  
  91.                             { field: "Discontinued", width: 120 },  
  92.                             { command: "destroy", title: " ", width: 150 }],  
  93.                         editable: true  
  94.                     });  
  95.                 });  
  96.             </script>  
  97.         </div>  
  98. </body>  
  99. </html>    

Result in Browser

 
I hope you have enjoyed this blog. Your valuable feedback, questions, and comments about this blog are always welcome.