Trying to prevent typing certain characters in RadGrid cells isn't working.

1 Answer 44 Views
Grid
Thomas
Top achievements
Rank 1
Iron
Iron
Iron
Thomas asked on 31 Mar 2022, 08:55 PM | edited on 01 Apr 2022, 01:54 PM

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?

1 Answer, 1 is accepted

Sort by
1
Accepted
Attila Antal
Telerik team
answered on 05 Apr 2022, 10:14 AM

Hi Thomas,

The OnKeyPress was mainly designed to handle the Grid's built-in Keyboard Support functionality.

If you look at the source code, the set_cancel(true) does not prevent typing in the key. It will only exit the JS code preventing further handling of the Keyboard actions related to the Keyboard support.

_raiseKeyPressInternal: function (e)
{
    var args = new Telerik.Web.UI.GridKeyPressEventArgs(e);
    this.raise_keyPress(args);

    if (args.get_cancel()) // if canceled
    {
        return; // exit the code. this does not prevent the input
    }

    this._handleGridKeyboardAction(e); // otherwise, handle the Grid KeyBoard actions
}

 

So if you wanted to prevent a certain key to be entered, you should explicitly cancel that event. To do so, access the original dom Event instead of the Grid's delegated event, and call the preventDefault() method.

function OnKeyPress(sender, args) {

    var domEvent = args.get_domEvent();

    domEvent.preventDefault();

}

 

This will 100% prevent the key to be entered.

 

I hope this will be helpful.

 

Regards,
Attila Antal
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Thomas
Top achievements
Rank 1
Iron
Iron
Iron
commented on 05 Apr 2022, 12:19 PM

Thank you. It works perfectly now.
Tags
Grid
Asked by
Thomas
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Attila Antal
Telerik team
Share this question
or