I have a web application that dynamically builds its rows and columns. The data type is specified for each row in column 2. As you see in the ASPX code below, I use the OnKeyPress client-side event to try to prevent letters from being entered into numeric fields (R for real, and I for integer).
ASPX:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<telerik:RadStyleSheetManager ID="RadStyleSheetManager1" runat="server" />
</head>
<body>
<form id="form1" runat="server">
<telerik:RadScriptManager ID="RadScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" />
<asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" />
<asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js" />
</Scripts>
</telerik:RadScriptManager>
<script type="text/javascript">
function OnGridCreated(sender, args) {
// Resize columns to fit data
var grid = sender;
var gridElement = grid.get_element();
// Attach the keydown event
$telerik.$(gridElement).on('keydown', OnKeyDown);
var masterTable = grid.get_masterTableView();
var columns = masterTable.get_columns();
// Resize all Columns
columns.forEach(col => col.resizeToFit());
// Collect the width of all columns
var allColumnsWidth = columns.map(col => col.get_element().offsetWidth);
// Get the Frozen Scroll
var frozenScroll = $telerik.$(gridElement).find('div[id$=_Frozen]').get(0);
var scrollLeftOffset = 0;
var lastWidth = 0;
// Assign function to recalculate scrolling
$telerik.$(grid.GridDataDiv).on('scroll', function (e) {
for (var i = 0; i < columns.length; i++) {
if (!columns[i].get_visible()) {
scrollLeftOffset += allColumnsWidth[i];
lastWidth = allColumnsWidth[i];
}
}
var thisScrollLeft = this.scrollLeft;
this.scrollLeft = 0;
if (thisScrollLeft > 0) {
// To insure the current cell is not on the right edge, add the last column's width
frozenScroll.scrollLeft = thisScrollLeft + scrollLeftOffset + lastWidth;
}
scrollLeftOffset = 0;
})
}
function OnKeyDown(event) {
// Look for TAB
if (event.which == 9) {
var gridElement = event.currentTarget;
var grid = gridElement.control;
var masterTableView = grid.get_masterTableView();
var target = event.target;
var currentCell = $telerik.$(target).closest('td.rgBatchCurrent').get(0);
if (!currentCell) return;
var cellIndex = currentCell.cellIndex;
var numColumns = masterTableView.get_columns().length - 1;
var frozenScroll = $telerik.$(gridElement).find('div[id$=_Frozen]').get(0);
if (!event.shiftKey) {
if (cellIndex == numColumns) {
// Reset scroll position to left edge
frozenScroll.scrollLeft = 0;
}
}
else {
// Reduce the scroll position by the current cell's width
frozenScroll.scrollLeft = frozenScroll.scrollLeft - currentCell.offsetWidth;
}
}
}
function OnKeyPress(sender, args)
{
// What is the key that was pressed
var c = args.get_keyCode();
// What is this row's data type (second column)
var d = args._domEvent.rawEvent.path[3].cells[1].textContent.trim();
var isNumeric = (c >= 48 && c <= 57); // 0 through 9
var isNegative = (c == 45); // hyphen or minus
var isSymbol = (c == 44) || (c == 46); // comma or period
var isModifier = (args._isAltPressed || args._isCtrlPressed || args._isShiftPressed);
console.log(c);
console.log(d);
console.log(isNumeric);
console.log(isNegative);
console.log(isSymbol);
console.log(isModifier);
if (d == 'S') {
// string allows everything
args.set_cancel(false);
} else if (d == 'I') {
// integer allows numbers and minus
var xxx = !((isNumeric || isNegative) && !isSymbol && !isModifier);
console.log(xxx)
args.set_cancel(xxx);
} else if (d == 'R') {
var xxx = !((isNumeric || isNegative || isSymbol) && !isModifier);
console.log(xxx)
// real allows numbers, minus, comma, and decimal
args.set_cancel(xxx);
}
}
</script>
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
</telerik:RadAjaxManager>
<div>
<telerik:RadGrid ID="RadGrid1" runat="server"
OnNeedDataSource="RadGrid1_NeedDataSource"
AutoGenerateColumns="False">
<ClientSettings AllowKeyboardNavigation="True">
<Scrolling FrozenColumnsCount="2" AllowScroll="True" ScrollHeight="600px" UseStaticHeaders="True"></Scrolling>
<Selecting CellSelectionMode="None" AllowRowSelect="True"></Selecting>
<ClientEvents OnGridCreated="OnGridCreated" OnKeyPress="OnKeyPress" />
<Resizing AllowColumnResize="True" AllowResizeToFit="True" ClipCellContentOnResize="False" />
</ClientSettings>
<AlternatingItemStyle Wrap="True" BackColor="Gainsboro"></AlternatingItemStyle>
<MasterTableView CommandItemDisplay="TopAndBottom" DataKeyNames="PeopleID" EditMode="Batch" TableLayout="Fixed">
<BatchEditingSettings EditType="Row" />
<Columns>
</Columns>
<CommandItemSettings ShowAddNewRecordButton="False" />
</MasterTableView>
<HeaderStyle VerticalAlign="Bottom" Font-Bold="True" BackColor="DarkSeaGreen" Wrap="False"></HeaderStyle>
<ActiveItemStyle Wrap="True"></ActiveItemStyle>
</telerik:RadGrid>
</div>
</form>
</body>
</html>
C#:
using System;
using Telerik.Web.UI;
using System.Data;
public partial class Default : System.Web.UI.Page
{
protected void RadGrid1_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
DataTable dt = new DataTable();
DataRow dr;
int rowsNum = 130;
string[][] colsInfo = {
new string[] { "PeopleID", "number" },
new string[] { "Type", "string" },
new string[] { "Custom1", "string" },
new string[] { "Custom2", "string" },
new string[] { "Custom3", "string" },
new string[] { "Custom4", "string" },
new string[] { "Custom5", "string" },
new string[] { "Custom6", "string" },
new string[] { "Custom7", "string" },
new string[] { "Custom8", "string" },
new string[] { "Custom9", "string" },
new string[] { "Custom10", "string" },
new string[] { "Custom11", "string" },
new string[] { "Custom12", "string" },
new string[] { "Custom13", "string" },
new string[] { "Custom14", "string" },
new string[] { "Custom15", "string" },
new string[] { "Custom16", "string" },
new string[] { "Custom17", "string" },
new string[] { "Custom18", "string" },
new string[] { "Custom19", "string" },
new string[] { "Custom20", "string" },
};
for (int i = 0; i < colsInfo.Length; i++)
{
GridBoundColumn newColumn = new GridBoundColumn();
newColumn.DataField = colsInfo[i][0];
newColumn.UniqueName = colsInfo[i][0];
newColumn.HeaderText = "*" + colsInfo[i][0] + "*";
RadGrid1.MasterTableView.Columns.Add(newColumn);
switch (colsInfo[i][1])
{
case "string":
dt.Columns.Add(new DataColumn(colsInfo[i][0], typeof(String)));
break;
case "number":
dt.Columns.Add(new DataColumn(colsInfo[i][0], typeof(Int32)));
break;
case "date":
dt.Columns.Add(new DataColumn(colsInfo[i][0], typeof(DateTime)));
break;
case "bool":
dt.Columns.Add(new DataColumn(colsInfo[i][0], typeof(Boolean)));
break;
default:
break;
}
}
for (int j = 1; j <= rowsNum; j++)
{
dr = dt.NewRow();
for (int k = 0; k < colsInfo.Length; k++)
{
switch (colsInfo[k][1])
{
case "string":
string x = "";
if (k == 1)
{
if ((j % 3) == 0)
x = "S";
else if ((j % 2) == 0)
x = "I";
else
x = "R";
}
dr[colsInfo[k][0]] = x;
break;
case "number":
dr[colsInfo[k][0]] = j;
break;
case "date":
dr[colsInfo[k][0]] = DateTime.Now;
break;
case "bool":
dr[colsInfo[k][0]] = j % 2 == 1 ? true : false;
break;
default:
break;
}
}
dt.Rows.Add(dr);
}
(sender as RadGrid).DataSource = dt;
}
}
If I type a letter into any cell of a row with an "I" or "R" in the second column, I want it to ignore that character. The console.log() calls confirm that the variables in my JavaScript function are what I expect them to be, but the args.set_cancel(true) calls are not doing what I expect.
What do I need to do to get this character validation working?
What improvements/optimizations can be made to the OnKeyPress() function?