Kendo jQuery Inline Grid Validation is not working as needed - validation

I'm trying to use KENDO UI to validated 2 values in a grid row.
These 2 values, HOURS and COUNT are mutually exclusive, so if they both have a value > 0, I would like to signal an error.
Two behavior issues I'm having:
The error "Both Hours and Count are not allowed" displays, but it only triggers on the second iteration of erroneous input.
Example input: Hours / Count
1 0 (good)
1 1 (should result an error)
1 2 (this fires the desired error)
Once the error displays, I can't determine how to remove it. If I correct the data setting one of the inputs back to zero, the error remains.
I'm using function FCTest to validate, but I can only assume I need to call it again, or in a different sequence to get the timing corrected.
Thanks,
Robert
My Code:
<!DOCTYPE html>
<!-- TEST -->
<html>
<head>
<base href="http://demos.telerik.com/kendo-ui/grid/editing-custom-validation">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2016.2.504/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2016.2.504/styles/kendo.material.min.css" />
<script src="//kendo.cdn.telerik.com/2016.2.504/js/jquery.min.js"></script>
<script src="//kendo.cdn.telerik.com/2016.2.504/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid"></div>
<script>
$(document).ready(function () {
dataSource = new kendo.data.DataSource({
data: [
{ id: 1, count: 1, hours: 0},
{ id: 2, count: 0, hours: 1},
],
pageSize: 20,
schema: {
model: {
id: "id",
fields: {
id: { editable: false },
count: {editable: true,type: "number",
validation:{
required:true,
maxlength:"3",
FCValid: FCTest}},
hours: {editable: true, type: "number",
validation:{required:true,
maxlength:"2"}}}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
pageable: true,
height: 550,
toolbar: ["create"],
columns: [
{field: "id", title: "ID", format: "{0:c}", width: "120px"},
{field: "count", title: "Count", width: "120px"},
{field: "hours", title: "Hours", width: "120px"},
{command: ["edit", "destroy"], title: " ", width: "250px"}],
editable: "inline"
});
}); // end document ready
function FCTest(input) {
var row = input.closest("tr");
var grid = row.closest("[data-role=grid]").data("kendoGrid");
var dataItem = grid.dataItem(row);
// if (parseFloat(input.val()) <= .1) {
// input.attr("data-FCValid-msg", "Decimals not allowed");
// return false;
// }
console.log({row});
console.log({dataItem});
console.log(dataItem.hours);
console.log(dataItem.count);
if (parseFloat(dataItem.hours) > 0 && (parseFloat(dataItem.count) > 0)) {
input.attr("data-FCValid-msg", "Both Hours and Count are not allowed");
return false;
}
if (parseFloat(dataItem.hours) == 0 && (parseFloat(dataItem.count) == 0)) {
input.attr("data-FCValid-msg", "Must contain one Frequency value: Hours or Count");
return false;
}
return true;
}
</script>
</body>
</html>

Subscribe to the cellClose, check if the incoming model is not a new row, and then check if the values meet your conditions:
cellClose: function(e) {
if (!e.model.isNew()) {
if (e.model.count > 0 && e.model.hours > 0) {
kendo.alert('Both Hours and Count are not allowed');
} else if (e.model.count == 0 && e.model.hours == 0) {
kendo.alert('Must contain one Frequency value: Hours or Count');
}
}
}
Dojo: https://dojo.telerik.com/oxAkUpAs

Related

Formatters give incorrect result after sort or search

I have following code using free-jqgrid. It loads correctly for the first time (Status is “Active” and Partner? is “Yes”). But when I do a sort or search, the values become incorrect(Status is “Retired” and Partner? is “No”).
Why the formatters are giving incorrect values? How to fix this?
SCRIPT
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/themes/start/jquery-ui.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.13.6/js/jquery.jqgrid.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/free-jqgrid/4.13.6/css/ui.jqgrid.min.css" rel="stylesheet" />
<script type="text/javascript">
function getCurrentPractice ()
{
return "Test";
}
function getGridCaption() {
return "<div style='font-size:15px; font-weight:bold; display:inline; padding-left:10px;'><span class='glyphicon glyphicon-check' style='margin-right:3px;font-size:14px;'></span>" + getCurrentPractice() + " " + "</div>" +
"<div style='float:right; padding-right:20px; padding-bottom:10px; display:inline;>" +
"<div style='float:right;width:550px; padding-bottom:20px;'>" +
"<input type='text' class='form-control' id='filter' placeholder='Search' style='width:250px; height:30px; float:right; ' />" +
" </div>" +
"</div>";
}
$(function () {
var currentPractice = "P";
var grid = $("#list2");
grid.jqGrid({
url: '/Home/GetProviders',
datatype: "json",
postData:
{
practiceName: function () { return currentPractice }
},
colNames: [
'Practice',
'ProviderID',
'Partner?',
'Status'
],
colModel: [
{ name: 'Practice', hidden: false },
{ name: 'ProviderID', hidden: false },
{
name: 'PartnerStatusText',
width: 70,
formatter: function (cellvalue, options, rowObject) {
var isPartner = rowObject.IsPartner;
return isPartner == true ? 'Yes' : 'No';
}
},
{
name: 'ActiveStatusText',
width: 70,
formatter: function (cellvalue, options, rowObject) {
var isActive = rowObject.IsActive;
return isActive == true ? 'Active' : 'Retired';
}
}
],
ignoreCase: true,
loadonce: true,
rowNum: 25,
rowList: [15, 25, 35, 50],
pager: '#pager2',
viewrecords: true,
sortable: true,
caption: getGridCaption(),
beforeSelectRow: function (rowid, e) {
//Avoid selection of row
return false;
},
loadComplete: function () {
}
});
grid.jqGrid('navGrid', '#pager2', { edit: false, add: false, del: false });
//Filter Toolbar
$("#advancedSearch").click(function () {
grid.jqGrid('filterToolbar', { stringResult: true, searchOnEnter: false, defaultSearch: "cn" });
});
//Top Search
$("#filter").on('keyup', function () {
var searchFiler = $("#filter").val(), f;
if (searchFiler.length === 0) {
grid[0].p.search = false;
$.extend(grid[0].p.postData, { filters: "" });
}
f = { groupOp: "OR", rules: [] };
f.rules.push({ field: "Practice", op: "cn", data: searchFiler });
grid[0].p.search = true;
$.extend(grid[0].p.postData, { filters: JSON.stringify(f) });
grid.trigger("reloadGrid", [{ page: 1, current: true }]);
});
});
</script>
</head>
HTML
<div style="float:left; border:1px solid red;">
<div id="divGrid" style="width: 680px; min-height: 50px; float: left; border: 1px solid silver;">
<table id="list2"></table>
<div id="pager2"></div>
</div>
</div>
Server Code
[AllowAnonymous]
public JsonResult GetProviders(string practiceName)
{
//System.Threading.Thread.Sleep(3000);
List<Provider> providers = new List<Provider>();
Provider p = new Provider();
p.Practice = "Test1";
p.ProviderID = 1;
p.IsActive = true;
p.IsPartner = true;
providers.Add(p);
Provider p2 = new Provider();
p2.Practice = "Test2";
p2.ProviderID = 2;
p2.IsActive = true;
p2.IsPartner = true;
providers.Add(p2);
return Json(providers, JsonRequestBehavior.AllowGet);
}
UPDATE
Thanks to Oleg, working demo can be found here - Fiddle . It uses "/echo/json/" service of JSFiddle to get data from server.
It uses sorttype and additionalProperties. This can be rewritten without additionalProperties - I need to do it when I get a chance to revisit this.
The problem seems be very easy. The data returned from the server contains properties Practice, ProviderID, IsActive and IsPartner. The properties are available in rowObject during initial loading. You use additionally loadonce: true option. Thus free jqGrid will try to save some data locally, but which one? jqGrid saves by default the properties which corresponds the names of columns: Practice, ProviderID, PartnerStatusText and ActiveStatusText, but jqGrid have no information that other properties IsActive and IsPartner need be saved too.
You can solve the problem in two alternative ways:
you rename the column names PartnerStatusText and ActiveStatusText to IsActive and IsPartner.
you add the option additionalProperties: ["IsActive", "IsPartner"] to inform jqGrid to read and save locally additional properties.
Moreover, I'd recommend you to use options.rowData instead of rowObject inside of custom formatter. You can skip the 3-d parameter and to use formatter: function (cellvalue, options) {...}.
The final remark: the current code of the custom formatter is very easy. You need to replace some input values (true and false) to another text. One can use formatter: "select" for the case:
colModel: [
{ name: "Practice" },
{ name: "ProviderID" },
{
name: "IsPartner",
width: 70,
formatter: "select",
formatoptions: { value: "false:No;true:Yes" }
},
{
name: "IsActive",
width: 70,
formatter: "select",
formatoptions: { value: "false:Retired;true:Active" }
}
],
See https://jsfiddle.net/c9fge9yk/1/

How to disable the cell if the date is empty or null or undefined?

I'm new to jqgrid and jquery, can someone please help me in disabling the cell when the date is null or empty or undefined?
Actually the json for some (rows,col) date data is there and for some it is not there.
I want to disable the cell in the row for which Date data is not available.
grid cell editing POC
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" type="text/css" href="/jqGrid/jquery-ui-1.11.4.custom/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="/jqGrid/Guriddo_jqGrid_JS_5.0.1/css/ui.jqgrid.css">
<script type="text/ecmascript" src="/jqGrid/Guriddo_jqGrid_JS_5.0.1/js/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/jqGrid/jquery-ui-1.11.4.custom/jquery-ui.min.js"></script>
<script type="text/javascript" src="/jqGrid/Guriddo_jqGrid_JS_5.0.1/js/i18n/grid.locale-en.js"></script>
<script type="text/javascript">
$.jgrid.useJSON = true;
</script>
<script type="text/javascript" src="/jqGrid/Guriddo_jqGrid_JS_5.0.1/src/jquery.jqGrid.js"></script>
<script type="text/javascript">
$(function () {
"use strict";
var grid = $("#tree");
var initDateWithButton = function (elem) {
var ids = grid.jqGrid('getDataIDs');
for (var i=0;i<ids.length;i++) {
var id=ids[i];
if (grid.jqGrid('getCell',id,'assignedDate') == null) {
grid.jqGrid('setCell',id,'assignedDate','','not-editable-cell');
}
if (grid.jqGrid('getCell',id,'assignedDate') == "") {
grid.jqGrid('setCell',id,'assignedDate','','not-editable-cell');
}
if (grid.jqGrid('getCell',id,'assignedDate') == undefined) {
grid.jqGrid('setCell',id,'assignedDate','','not-editable-cell');
}
}
if (/^\d+%$/.test(elem.style.width)) {
// remove % from the searching toolbar
elem.style.width = '';
}
// to be able to use 'showOn' option of datepicker in advance searching dialog
// or in the editing we have to use setTimeout
setTimeout(function () {
$(elem).datepicker({
dateFormat: 'dd-M-yy',
showOn: 'button',
changeYear: true,
changeMonth: true,
showWeek: false,
showButtonPanel: true,
buttonImage: 'http://rcban0015:10039/GridPOC/pages/calenderIcon.gif',
onClose: function (dateText, inst) {
inst.input.focus();
}
});
$(elem).next('button.ui-datepicker-trigger').button({
text: false,
position: "relative",
top: "4px"
});
}, 100);
},
dateTemplate = {align: 'center', sorttype: 'date', editable: true,
formatter: 'date', formatoptions: { newformat: 'd-M-Y' }, datefmt: 'd-M-Y',
editoptions: { dataInit: initDateWithButton, size: 11 },
searchoptions: {
sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'],
dataInit: initDateWithButton,
size: 11, // for the advanced searching dialog
attr: {size: 11} // for the searching toolbar
}},
lastSel;
jQuery('#tree').jqGrid({
url: '<%= webAppAccess.getBackchannelActionURL("actionListjqGridPagination",false) %>',
"colModel":[
{
"name":"course_id",
"index":"course_id",
"sorttype":"int",
"key":true,
"hidden":true,
"width":50
},{
"name":"courseName",
"index":"courseName",
"sorttype":"string",
"label":"courseName",
"width":200
},{
"name":"facility",
"index":"facility",
"label":"facility",
"width":200,
"align":"left"
},{
"name":"assignedDate",
"index":"assignedDate",
"label":"assignedDate",
"width":110,
"template": dateTemplate
},{
"name":"dueDate",
"index":"dueDate",
"label":"dueDate",
"width":110,
"template": dateTemplate
},
{
"name":"AssignmentStatus",
"index":"AssignmentStatus",
"label":"AssignmentStatus",
"width":50
},{
"name":"Action",
"index":"Action",
"label":"Action",
"width":50
},
{
"name":"lft",
"hidden":true
},{
"name":"rgt",
"hidden":true
},{
"name":"level",
"hidden":true
},{
"name":"uiicon",
"hidden":true
}
],
"jsonReader": { "repeatitems": false, "root": "employees.rows" },
"toolbar": [true, "top"],
"width":"1200",
"hoverrows":false,
"viewrecords":false,
"gridview":true,
"height":"auto",
"sortname":"lft",
"loadonce":true,
"rowNum": 2,
"rowList":[2,10,15],
"scrollrows":true,
// enable tree grid
"treeGrid":true,
// which column is expandable
"ExpandColumn":"courseName",
// datatype
"treedatatype":"json",
// the model used
"treeGridModel":"nested",
// configuration of the data comming from server
"treeReader":{
"left_field":"lft",
"right_field":"rgt",
"level_field":"level",
"leaf_field":"isLeaf",
"expanded_field":"expanded",
"loaded":"loaded",
// set the ui icon field froom data
"icon_field":"uiicon"
},
"sortorder":"asc",
"datatype":"json",
"pager":"#pager",
"cellEdit": true, // TRUE = turns on celledit for the grid.
"cellsubmit" : 'clientArray',
"editurl": 'clientArray'
});
$('#t_' +"tree")
.append($("<div><label for=\"globalSearchText\">Global search in grid for: </label><input id=\"globalSearchText\" type=\"text\"></input> <button id=\"globalSearch\" type=\"button\">Search</button></div>"));
$("#globalSearchText").keypress(function (e) {
var key = e.charCode || e.keyCode || 0;
if (key === $.ui.keyCode.ENTER) { // 13
$("#globalSearch").click();
}
});
$("#globalSearch").button({
icons: { primary: "ui-icon-search" },
text: false
}).click(function () {
var postData = jQuery('#tree').jqGrid("getGridParam", "postData"),
colModel = jQuery('#tree').jqGrid("getGridParam", "colModel"),
rules = [],
searchText = $("#globalSearchText").val(),
l = colModel.length,
i,
cm;
for (i = 0; i < l; i++) {
cm = colModel[i];
if (cm.search !== false && (cm.stype === undefined || cm.stype === "text")) {
rules.push({
field: cm.name,
op: "cn",
data: searchText
});
}
}
postData.filters = JSON.stringify({
groupOp: "OR",
rules: rules
});
jQuery('#tree').jqGrid("setGridParam", { search: true });
jQuery('#tree').trigger("reloadGrid", [{page: 1, current: true}]);
return false;
});
});
</script>
</head>
<body>
<table id="tree"><tr><td></td></tr></table>
<div id="pager"></div>
</body>
</html>
There are exist alternative fork of jqGrid: free jqGrid, which I develop since more as one year. It has the functionality, where one can define editable property of colModel as function, which can return true or false based on the cell or the row content. See the wiki article for more details.
Check if this How to disable editing for soe cells in row editing of JQGrid
helps, it seen it is a similar thing, You just need to add into your logic.

kendo customised TreeList manual adding childnode unexpected result

List item
I have a page which loads a kendo TreeList by pressing a button. The data is for the moment statically defined in a variable where it stays as a basis for the Kendo TreeList datasource.
I have a datasource definition which I mostly copied from Telerik Website.
I have a treelist with a couple of requirements in terms of CRUD.
level1 - nothing
level2 - add new childnodes only
level3 - edit and delete
Edit should be doubleclick on a level3 item
CRUD command buttons need to be icon-only (no text in the buttons)
I could not achieve this with the buildin CRUD controls unfortunately so I used a Template column where the buttons are placed based on their "Type" field.
Now this has worked but after some changes which I can't undo somehow the add function does not work anymore. It works but new childnode is only visible after a edit ordelete of another node. (as if the change event is not triggered during add). The Add button in the treeList calls a function addProduct where at the end I try to pushCreate directly to the datasource. However the Transport.create is never invoked. It only gets invoked after another Crud action triggers it
Can anybody see what's wrong and couldn't this all be achieve with much easier approach?
Here's the page:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Kendo UI Grid - CRUD operations with local data</title>
<style>
html {
font-size: 12px;
font-family: Arial, Helvetica, sans-serif;
}
</style>
<link href="styles/kendo.common.min.css" rel="stylesheet" />
<link href="styles/kendo.default.min.css" rel="stylesheet" />
<script src="Scripts/jquery-2.1.3.min.js"></script>
<!--<script src="Scripts/kendo.all.min.js"></script>-->
<script src="Scripts/kendo.all.js"></script>
</head>
<body>
<style>
.hidden {
display: none;
}
.k-grid tbody .k-button, .k-ie8 .k-grid tbody button.k-button {
min-width: 0px;
padding-left: 10px;
padding-right: 0px;
padding-bottom: 0px;
padding-top: 0px;
margin: 0px;
}
</style>
<div id="buttons">
<br />
<p>
<button name="clear" id="clear" onclick="myclear()">Clear grid</button>
<button name="load" id="load" onclick="loadLocal()">Load from local DB</button>
</p>
<br />
version 1.01<br />
<br />
</div>
<div id="treelist"></div>
<script id="btn-template" type="text/x-kendo-template">
# if (Code == "Product") { #
<a id="btnupdate" class="k-button k-button-icontext k-grid-update column hidden" title="Update product" onclick="update(this)" href="\#"><span class="k-icon k-update"></span></a>
<a id="btndelete" class="k-button k-button-icontext k-grid-delete column" title="Delete product" data-command="destroy" href="\#"><span class="k-icon k-delete"></span></a>
# } else if (Code == "Requirement") { #
<a class="k-button k-button-icontext k-grid-add column" title="Add a product to this requirement" onclick="addProduct(this)" href="\#"><span class="k-icon k-add"></span></a>
# } #
</script>
<script>
var EPDdata // For holding the data of the TreeList
function loadLocal() {
EPDdata = [
{ Id: 1, Description: "Item1", Code: "Category", parentId: null },
{ Id: 2, Description: "Item2", Code: "Requirement", parentId: 1 },
{ Id: 3, Description: "Item3", Code: "Product", parentId: 2 },
{ Id: 4, Description: "Item4", Code: "Requirement", parentId: 1 },
{ Id: 5, Description: "Item5", Code: "Product", parentId: 4 },
{ Id: 6, Description: "Item6", Code: "Product", parentId: 4 },
{ Id: 7, Description: "Item7", Code: "Requirement", parentId: 1 },
{ Id: 8, Description: "Item8", Code: "Requirement", parentId: 1 },
{ Id: 9, Description: "Item9", Code: "Product", parentId: 8 },
{ Id: 10, Description: "Item10", Code: "Product", parentId: 8 }
]
LoadTree();
};
function LoadTree() {
var EPDdataNextID = EPDdata.length + 1;
var LocaldataSource = new kendo.data.TreeListDataSource({
transport: {
read: function (e) {
// on success
e.success(EPDdata);
},
create: function (e) {
// assign an ID to the new item
e.data.Id = EPDdataNextID++;
// save data item to the original datasource
EPDdata.push(e.data);
// on success
e.success(e.data);
},
update: function (e) {
// locate item in original datasource and update it
EPDdata[getIndexById(e.data.Id)] = e.data;
// on success
e.success();
},
destroy: function (e) {
// locate item in original datasource and remove it
EPDdata.splice(getIndexById(e.data.Id), 1);
// on success
e.success();
}
},
error: function (e) {
// handle data operation error
alert("Status: " + e.status + "; Error message: " + e.errorThrown);
},
pageSize: 10,
expanded: true,
batch: false,
schema: {
model: {
id: "Id",
expanded: true,
fields: {
Id: { type: "number", editable: false, nullable: true },
Description: { type: "string", validation: { required: true } },
Code: { type: "string" },
parentId: { type: "number", editable: true, nullable: true }
}
}
}
});
$("#treelist").empty(); // only 1 treelist on the page please
$("#treelist").kendoTreeList({
dataSource: LocaldataSource,
pageable: false,
edit: onEdit,
columns: [
{ field: "Description", title: "Description", width: "400px" },
{ field: "Code", width: "120px" },
{ field: "Id", title: "ID", width: "30px" },
{ field: "parentId", title: "PID", width: "30px" },
{ width: "35px", template: $("#btn-template").html() },
{ command: ["create", "edit", "destroy"] }
],
editable: "inline"
});
var treeList = $("#treelist").on("dblclick", function (e) {
var treeList = $("#treelist").data("kendoTreeList");
var rowindex = e.target.parentNode.rowIndex; // get rowindex
var tr = $(e.target).closest("tr"); // get the current table row (tr)
var dataItem = $("#treelist").data("kendoTreeList").dataItem(tr);
if (dataItem.Code == "Product") {
$("#treelist").find(".edit").addClass("hidden");
$("#treelist").find(".edit").removeClass("edit");
$("#treelist").find(".delete").removeClass("hidden");
$("#treelist").find(".delete").removeClass("delete");
treeList.saveRow(); // first save all other rows
treeList.editRow(tr[0]);
};
}); // double click function
}; // Function CreatetreeList
function onEdit(arg) {
var tr = $(arg.container);//.closest("tr"); // get the current table row (tr)
tr.find("#btndelete").addClass("hidden"); //remove btndelete from commandcolumn
tr.find("#btndelete").addClass("delete"); //put class to select the btn later on
tr.find("#btnupdate").removeClass("hidden"); //make btnupdate visible in commandcolumn
tr.find("#btnupdate").addClass("edit"); //put class to select the btn later on
};
function update(e) { // update the edited row
var tr = $(e).closest("tr"); // get the current table row (tr)
var treeList = $("#treelist").data("kendoTreeList");
treeList.saveRow();
tr.find("#btndelete").removeClass("hidden");
tr.find("#btndelete").removeClass("delete");
tr.find("#btnupdate").addClass("hidden");
tr.find("#btnupdate").removeClass("edit");
};
function addProduct(e) {
var treeList = $("#treelist").data("kendoTreeList");
var dataSource = treeList.dataSource;
var data = dataSource.data;
var tr = $(e).closest("tr"); // get the current table row (tr)
var dataItem = treeList.dataItem(tr);
dataSource.pushCreate({ Id: 15, Description: "New", Code: "Product", parentId: dataItem.Id });
alert("Done");
};
function getIndexById(id) {
var idx,
l = EPDdata.length;
for (var j; j < l; j++) {
if (EPDdata[j].Id == id) {
return j;
}
}
return null;
}
</script>
</body>
</html>
I found the answer !!!
The datasource pagesize is set to 10 and the TreeList was set to paging: false. In all my tests I started with sample data of 10 nodes. All the time I was adding an 11th and 12th record which wasn't showing up until I deleted another node...
Do these things only happen to me?

KendoUI: cannot sort sale column with comma in grid

i have this HTML code, I cannot make it sorted on sale column, please help how to do that, I've tried to implement this solution How to sort numeric with string values in Kendo-Grid , but still failed.
<html>
<head>
<link href="lib/kendo/styles/examples-offline.css" rel="stylesheet">
<link href="lib/kendo/styles/kendo.common.min.css" rel="stylesheet">
<link href="lib/kendo/styles/kendo.default.min.css" rel="stylesheet">
<script src="lib/js/jquery-ui-1.8.2.custom.min.js"></script>
<script src="lib/kendo/js/jquery.min.js"></script>
<script src="lib/kendo/js/kendo.web.min.js"></script>
<script src="lib/kendo/js/console.js"></script>
</head>
<body>
<div id="example" class="k-content">
<div class="demo-section">
<table id="grid">
<thead>
<tr>
<th data-field="product">Product</th>
<th data-field="sale">Sale</th>
</tr>
</thead>
<tbody>
<tr style=display:none><td>A</td><td>6,698</td></tr>
<tr style=display:none><td>B</td><td>10,900</td></tr>
<tr style=display:none><td>C</td><td>2,300</td></tr>
<tr style=display:none><td>D</td><td>700</td></tr>
</tbody>
</table>
<script>
$(document).ready(function() {
$("#grid").kendoGrid({
dataSource: {
pageSize: 200
},
height: 350,
sortable: true,
filterable: true,
groupable: true,
pageable: {
refresh: true,
pageSizes: true
},
columns: [ {
field: "product",
width: 200
} , {
field: "sale",
sortable: {
compare: function(a, b) {
var x = a.sale.replace(/\,/g,'');
var y = b.sale.replace(/\,/g,'');
return x - y;
}
},
filterable: false,
width: 100
}
]
});
});
</script>
<style scoped="scoped">
.demo-section {
width: 800px;
}
.demo-section h3 {
margin: 5px 0 15px 0;
text-align: center;
}
</style>
</div>
</div>
</body>
</html>
The problem is that you never say that sale is actually a number so despite you remove , they are still getting strings.
You have to do:
Option 1: use kendo.parseInt to parse sale into numbers (depending on your culture it will take care of , as thousand separator).
sortable: {
compare: function(a, b) {
var x = kendo.parseInt(a.sale);
var y = kendo.parseInt(b.sale);
console.log(a.sale,x);
console.log(b.sale,y);
return x - y;
}
},
Option 2: Declare that the column is a number and say to display it with thousand separator. Then you DataSource would be:
dataSource: {
pageSize: 200,
schema: {
model: {
fields : {
sale : { type : "number" }
}
}
}
},
and you columns definition:
columns: [
{ field: "product", width: 200 } ,
{ field: "sale", filterable: false, width: 100, format : "{0:##,#}" }
]
NOTE: For this second alternative you don't need to define compare function. So your code would be:
$("#grid").kendoGrid({
dataSource: {
pageSize: 200,
schema : {
model: {
fields: {
sale: { type: "number" }
}
}
}
},
height : 350,
sortable : true,
filterable: true,
groupable : true,
pageable : {
refresh : true,
pageSizes: true
},
columns : [
{ field: "product", width: 200 } ,
{ field: "sale", filterable: false, width: 100, format: "{0:##,#}" }
]
});

JqGrid frozen column

I've been trying to add frozen column in my jqgrid but i found out there is bug with the last row of my data.
.
.
.
{name:'Code',index:'txt_site_code', hidden:false, align:'center', width:70, frozen:true }
.
.
}); /* end of jqgrid */
jQuery("#production").jqGrid('setFrozenColumns');
Why does the last row does not froze as it should. It will move with the horizontal scroller.
I saw the same 'bug' in trirand.com and trirand.net DEMO on FROZEN COLUMN topic. Any idea on how to solve this..?
thanks..
This happens when the height of the table is not equal to the height of the Div in which it is nested.
You can use jQuery to reassign the height of the table which is frozen.
Note: Use this on GridComplete Function.
$(".frozen-bdiv").height(j$(".frozen-bdiv").find("table").height());
The column height issue has not been resolved in jqGrid4.8.2. Using Oleg's solution from 'How to make Jqgrid frozen column word-wrap' works. See my code sample.
May you can add an onchange method.
This worked for me:
Add new height adjustment method:
function rowsHeightAdjust(){
editableRows = $("#jqGrid").find("tr");
frozenRows = $("#jqGrid_frozen").find("tr");
for (indexRow=0; indexRow<frozenRows.length;indexRow++){
if(indexRow > 0 && typeof(editableRows[indexRow]) != 'undefined') {
$(frozenRows[indexRow]).height($(editableRows[indexRow]).height());
}
}
}
Call the method on some event, eg:
//every time we change something on editable fields
$(".editable").change(function(){ rowsHeightAdjust() });
Jqgrid creates a new frozen table overlapping the editable one.
This method takes the frozen rows and makes each height match to editable row.
Hope you'll find it helpful.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>test page</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- A link to a jQuery UI ThemeRoller theme, more than 22 built-in and many more custom -->
<link rel="stylesheet" type="text/css" media="screen" href="/testGrid/Guriddo_jqGrid_JS_4_8_2/css/jquery-ui.css" />
<!-- The link to the CSS that the grid needs -->
<link rel="stylesheet" type="text/css" media="screen" href="/testGrid/Guriddo_jqGrid_JS_4_8_2/css/trirand/ui.jqgrid.css" />
<style type="text/css">
.ui-jqgrid .ui-jqgrid-bdiv { overflow-y: scroll;}
th.ui-th-column div {
/* see http://stackoverflow.com/a/7256972/315935 for details */
word-wrap: break-word; /* IE 5.5+ and CSS3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
white-space: pre-wrap; /* CSS3 */
overflow: hidden;
height: auto !important;
vertical-align: middle;
}
.ui-jqgrid tr.jqgrow td {
white-space: normal !important;
height: auto;
vertical-align: middle;
padding-top: 2px;
padding-bottom: 2px;
}
.ui-jqgrid .ui-jqgrid-htable th.ui-th-column {
padding-top: 2px;
padding-bottom: 2px;
}
.ui-jqgrid .frozen-bdiv, .ui-jqgrid .frozen-div {
overflow: hidden;
}
</style>
</head>
<body>
<table id="list"><tr><td /></tr></table>
<script type="text/ecmascript" src="/testGrid/Guriddo_jqGrid_JS_4_8_2/js/jquery.min.js"></script>
<script type="text/ecmascript" src="/testGrid/Guriddo_jqGrid_JS_4_8_2/js/jquery-ui.min.js"></script>
<script type="text/ecmascript" src="/testGrid/Guriddo_jqGrid_JS_4_8_2/js/trirand/i18n/grid.locale-en.js"></script>
<script type="text/ecmascript">
$.jgrid.no_legacy_api = true;
$.jgrid.useJSON = true;
</script>
<!--script type="text/javascript" src="/testGrid/jqGrid-master/jqGrid-master/js/jquery.jqGrid.js"></script-->
<script type="text/javascript" src="/testGrid/Guriddo_jqGrid_JS_4_8_2/js/trirand/jquery.jqGrid.min.js"></script>
<script type="text/javascript">
//<![CDATA[
/*global $ */
/*jslint unparam: true */
$(function () {
$(document).ready(function () {
$grid = $("#list"),
resizeColumnHeader = function () {
var rowHight, resizeSpanHeight,
// get the header row which contains
headerRow = $(this).closest("div.ui-jqgrid-view")
.find("table.ui-jqgrid-htable>thead>tr.ui-jqgrid-labels");
// reset column height
headerRow.find("span.ui-jqgrid-resize").each(function () {
this.style.height = '';
});
// increase the height of the resizing span
resizeSpanHeight = 'height: ' + headerRow.height() + 'px !important; cursor: col-resize;';
headerRow.find("span.ui-jqgrid-resize").each(function () {
this.style.cssText = resizeSpanHeight;
});
// set position of the dive with the column header text to the middle
rowHight = headerRow.height();
headerRow.find("div.ui-jqgrid-sortable").each(function () {
var $div = $(this);
$div.css('top', (rowHight - $div.outerHeight()) / 2 + 'px');
});
},
fixPositionsOfFrozenDivs = function () {
var $rows;
if (this.grid.fbDiv !== undefined) {
$rows = $('>div>table.ui-jqgrid-btable>tbody>tr', this.grid.bDiv);
$('>table.ui-jqgrid-btable>tbody>tr', this.grid.fbDiv).each(function (i) {
var rowHight = $($rows[i]).height(), rowHightFrozen = $(this).height();
if ($(this).hasClass("jqgrow")) {
$(this).height(rowHight);
rowHightFrozen = $(this).height();
if (rowHight !== rowHightFrozen) {
$(this).height(rowHight + (rowHight - rowHightFrozen));
}
}
});
$(this.grid.fbDiv).height(this.grid.bDiv.clientHeight);
$(this.grid.fbDiv).css($(this.grid.bDiv).position());
}
if (this.grid.fhDiv !== undefined) {
$rows = $('>div>table.ui-jqgrid-htable>thead>tr', this.grid.hDiv);
$('>table.ui-jqgrid-htable>thead>tr', this.grid.fhDiv).each(function (i) {
var rowHight = $($rows[i]).height(), rowHightFrozen = $(this).height();
$(this).height(rowHight);
rowHightFrozen = $(this).height();
if (rowHight !== rowHightFrozen) {
$(this).height(rowHight + (rowHight - rowHightFrozen));
}
});
$(this.grid.fhDiv).height(this.grid.hDiv.clientHeight);
$(this.grid.fhDiv).css($(this.grid.hDiv).position());
}
},
fixGboxHeight = function () {
var gviewHeight = $("#gview_" + $.jgrid.jqID(this.id)).outerHeight(),
pagerHeight = $(this.p.pager).outerHeight();
$("#gbox_" + $.jgrid.jqID(this.id)).height(gviewHeight + pagerHeight);
gviewHeight = $("#gview_" + $.jgrid.jqID(this.id)).outerHeight();
pagerHeight = $(this.p.pager).outerHeight();
$("#gbox_" + $.jgrid.jqID(this.id)).height(gviewHeight + pagerHeight);
};
// Define the grid
$("#list").jqGrid({
datatype: 'local',
//data: mydata,
colNames: ['Country', 'State', 'City', 'Attraction', 'longText', 'Zip code'],
colModel: [
{ name: 'country', width: 170, align: 'center', frozen: true, cellattr: arrtSetting, title:false},
{ name: 'state', width: 180, align: 'center', frozen: true},
{ name: 'city', width: 190 },
{ name: 'attraction', width: 120 },
{ name: 'longText', width: 80000 },
{ name: 'zip', index: 'tax', width: 160, align: 'right' }
],
cmTemplate: {sortable: false},
rowNum: 100,
//rowList: [5, 10, 20],
//pager: '#pager',
gridview: true,
hoverrows: false,
autoencode: true,
ignoreCase: true,
viewrecords: true,
loadComplete: updateSize,
resizeStop: updateSize,
//height: '100%', width: null, shrinkToFit: false,
height: '80', width: null, shrinkToFit: false,
caption: 'Grid with rowSpan attributes',
beforeSelectRow: function () {
return false;
}
});
$grid = $("#list")
jQuery("#list").jqGrid('setFrozenColumns');
$grid.jqGrid('gridResize', {
minWidth: 450,
stop: function () {
fixPositionsOfFrozenDivs.call(this);
fixGboxHeight.call(this);
},
loadComplete: function () {
fixPositionsOfFrozenDivs.call(this);
}
});
$grid.bind("jqGridResizeStop", function () {
resizeColumnHeader.call(this);
fixPositionsOfFrozenDivs.call(this);
fixGboxHeight.call(this);
});
// resizeColumnHeader.call($grid[0]);
// //$grid.jqGrid('setFrozenColumns');
// $grid.triggerHandler("jqGridAfterGridComplete");
// fixPositionsOfFrozenDivs.call($grid[0]);
// Data to be sent from various sources and aggregated...
var someLongText = "1111111111111111111111111111111111111111111111098888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww55555555555555555555555555555555555555555555555jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjsdfaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj4324333333333333333333333333333333333333333333333333333333333333333333333333333333555555555555555555555555555555555555555555555gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
var mydata = [
{ country: "USA", state: "Texas", city: "Houston", attraction: "NASA", longText: someLongText, zip: "77058" , attr: {country: {rowspan: "9"}} },
{ country: "USA", state: "Texas", city: "Austin", attraction: "6th street", zip: "78704", attr: {country: {display: "none"}} },
{ country: "USA", state: "Texas", city: "Arlinton", attraction: "Cowboys Stadium", zip: "76011" , attr: {country: {display: "none"}} },
{ country: "USA", state: "Texas", city: "Plano", attraction: "XYZ place", zip: "54643" , attr: {country: {display: "none"}} },
{ country: "USA", state: "Texas", city: "Dallas", attraction: "Reunion tower", zip: "12323" , attr: {country: {display: "none"}} },
{ country: "USA", state: "California", city: "Los Angeles", attraction: "Hollywood", zip: "65456", attr: {country: {display: "none"}} },
{ country: "USA", state: "California", city: "San Francisco", attraction: "Golden Gate bridge", zip: "94129" , attr: {country: {display: "none"}} },
{ country: "USA", state: "California", city: "San Diego", attraction: "See world", zip: "56653" , attr: {country: {display: "none"}} },
{ country: "USA", state: "California", city: "Anaheim", attraction: "Disneyworld", zip: "92802" , attr: {country: {display: "none"}} }
];
// Populate grid
for (var i = 0; i < mydata.length; i++) {
$("#list").jqGrid('addRowData', "myId_" + i, mydata[i], "last");
}
resizeColumnHeader.call($grid[0]);
//$grid.jqGrid('setFrozenColumns'); Already did this.
$grid.triggerHandler("jqGridAfterGridComplete");
fixPositionsOfFrozenDivs.call($grid[0]);
});
arrtSetting = function (rowId, val, rawObject, cm) {
var attr = rawObject.attr[cm.name];
var result;
if (attr.rowspan) {
result = ' rowspan=' + '"' + 9 + '"';
}
if (attr.display) {
result = ' style="display:' + attr.display + '"';
}
result = result + ' title=" this is the tooltip for ' + rowId + '"';
return result;
};
function updateSize(){
//getting all lines in two tables by they id
var lines = $("tr", this),
flines = $("tr", "#"+$(this).attr("id")+"_frozen" );
//setting in all frozen lines height equel to grid
flines.each(function(i, item){
//i%2 check because of border collapse
$(item).height( $(lines[i]).innerHeight() - (i%2?1:0) );
});
};
});
//]]>
</script>
</body>
</html>

Resources