Restricting Decimal Places in Kendo UI for jQuery Grid
Description
When working with numeric inputs in the Kendo UI for jQuery Grid, you might encounter several requirements such as restricting the number of decimal places, handling rounding, and allowing negative or null values. Addressing these needs ensures data integrity and user input accuracy in your application.
This knowledge base article also answers the following questions:
- How can I limit the number of decimal places in a numeric input?
- How do I round numeric input to a specific number of decimal places without trailing zeros?
- How can I allow negative and null values in numeric columns of the Grid?
Environment
Product | Kendo UI for jQuery Grid | Version | 2025.1.211 |
Solution
To address the described requirements, follow these steps:
Restricting Decimal Places and Handling Rounding
- Use the
NumericTextBox
as the editor for your numeric column. - Set the
decimals
option to limit the number of decimal places. - Use the
restrictDecimals
option to enforce the decimal limit. - Implement custom logic in the
change
event handler to handle rounding and maintain the desired decimal precision.
columns: [
{ field: "UnitPrice",
title: "Unit Price",
format: "{0:n5}",
editor: "NumericTextBox",
editorOptions: {
format: "n5",
decimals: 5,
restrictDecimals: true,
change: function(e) {
let tr = e.sender.element.closest("tr")
let dataitem = $("#grid").data("kendoGrid").dataItem(tr);
dataitem.set("UnitPrice", Math.round(e.sender.value() * 100000) / 100000);
}
},
width: 200 },
]
Allowing Negative and Null Values
- Ensure the model validation does not restrict negative values.
- Modify the editor's configuration to not implicitly disallow null values.
- Update the
change
event handler to accommodate null or blank values alongside the numeric input.
Example model validation configuration allowing negative values:
UnitPrice: { type: "number", validation: { required: true, min: -Infinity } },
Handling null or blank values in the change
event:
change: function(e) {
let tr = e.sender.element.closest("tr")
let dataitem = $("#grid").data("kendoGrid").dataItem(tr);
let inputValue = e.sender.value();
if(inputValue === null || inputValue === '') {
dataitem.set("UnitPrice", null);
} else {
dataitem.set("UnitPrice", Math.round(inputValue * 100000) / 100000);
}
}
For a complete implementation, refer to the below example.
<div id="grid"></div>
<script>
$(document).ready(function () {
var desiredValue,
paste = false;
var crudServiceBaseUrl = "https://demos.telerik.com/kendo-ui/service",
dataSource = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/Products",
dataType: "jsonp",
},
update: {
url: crudServiceBaseUrl + "/Products/Update",
dataType: "jsonp",
},
destroy: {
url: crudServiceBaseUrl + "/Products/Destroy",
dataType: "jsonp",
},
create: {
url: crudServiceBaseUrl + "/Products/Create",
dataType: "jsonp",
},
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
},
},
batch: true,
pageSize: 20,
schema: {
model: {
id: "ProductID",
fields: {
ProductID: { editable: false, nullable: true },
ProductName: { validation: { required: true } },
UnitPrice: {
type: "number",
validation: { required: false },
},
Discontinued: { type: "boolean" },
UnitsInStock: {
type: "number",
validation: { min: 0, required: true },
},
},
},
},
});
$("#grid").kendoGrid({
dataSource: dataSource,
navigatable: true,
pageable: true,
height: 550,
toolbar: ["create", "save", "cancel"],
columns: [
"ProductName",
{
field: "UnitPrice",
title: "Unit Price",
format: "{0:n5}",
editor: "NumericTextBox",
editorOptions: {
format: "n5",
decimals: 6,
restrictDecimals: true,
change: function (e) {
let tr = e.sender.element.closest("tr");
let dataitem = $("#grid").data("kendoGrid").dataItem(tr);
if (desiredValue) {
dataitem.set("UnitPrice", desiredValue);
}
if (!desiredValue) {
if (e.sender.value() == null) {
dataitem.set("UnitPrice", null);
} else {
dataitem.set(
"UnitPrice",
Math.round(e.sender.value() * 100000) / 100000,
);
}
}
},
},
width: 200,
},
{ field: "UnitsInStock", title: "Units In Stock", width: 120 },
{ field: "Discontinued", width: 120 },
{ command: "destroy", title: " ", width: 150 },
],
editable: true,
edit: function (e) {
e.container
.find("input[title='Unit Price']")
.on("paste", function (ev) {
paste = true;
let numerictTB = e.container
.find("input[name='UnitPrice']")
.data("kendoNumericTextBox");
let pastedData = (
ev.originalEvent.clipboardData || window.clipboardData
).getData("text");
desiredValue = Number(pastedData).toFixed(5);
numerictTB.value(desiredValue);
console.log("desiredValue", desiredValue);
numerictTB.trigger("change");
});
}
});
});
</script>