RadGrid Batch Edit Disable Specific Cells

1 Answer 17 Views
Grid
Richard
Top achievements
Rank 4
Iron
Iron
Iron
Richard asked on 06 Feb 2025, 06:35 PM

Afternoon,

I am using a RadGrid with Batch Editing.  Under a couple of conditions I want to be able to stop a cell from being edited.

I've followed another example using the OnBatchEditOpening client event:

        function onBatchEditOpening(sender, args) {
            args.get_tableView().get_dataItems();
            var cell = args.get_cell();
            var cellValue = cell.innerText;
            var columnUniqueName = args.get_columnUniqueName();
            var row = args.get_row();
            var item = row.control;
            var itemIndex = item.get_itemIndex();

            if (itemIndex > -1) { // if itemIndex is -1 it means this is a new row
                if ((columnUniqueName === "Process_type" && cellValue === "L") ||
                    (columnUniqueName === "Process_order" && cellValue === "1")) {
                    args.set_cancel(true);
                }
            }

It just so happens that when the process type is L and process order is 1 will occur in the same row, so all other rows should remain unaffected.

It works fine - I click in the row with 1 and L, and the process order and process type cells are not editable. However, when I then click on a field in another row I get this error:

This only occurs when I've clicked in the row with the non-editable cells first.

Any ideas on how to clear this?

Kind regards,

Richard

1 Answer, 1 is accepted

Sort by
0
Accepted
Vasko
Telerik team
answered on 10 Feb 2025, 09:19 AM

Hi Richard,

To address the issue you're encountering with RadGrid's Batch Editing, it seems like the error might be related to the way the grid is handling edit operations when switching between rows. When you prevent editing on specific cells, it's crucial to ensure that the grid's internal state is correctly managed to avoid conflicts when interacting with other rows.

Here's how you can handle this scenario:

  1. Ensure Proper Closure of Edit Operations: Before you prevent editing on specific cells, make sure that any existing edit operations are properly closed. This can help prevent conflicts when you try to interact with other rows.

  2. Modify the onBatchEditOpening Function: Adjust your JavaScript function to ensure that any necessary cleanup is done before canceling the edit. Here's an example:

    function onBatchEditOpening(sender, args) {
        // Close any other edit cells to clear potential conflicts
        sender.get_batchEditingManager()._tryCloseEdits(sender.get_masterTableView());
    
        var cell = args.get_cell();
        var cellValue = cell.innerText;
        var columnUniqueName = args.get_columnUniqueName();
        var row = args.get_row();
        var item = row.control;
        var itemIndex = item.get_itemIndex();
    
        if (itemIndex > -1) { // if itemIndex is -1 it means this is a new row
            if ((columnUniqueName === "Process_type" && cellValue === "L") ||
                (columnUniqueName === "Process_order" && cellValue === "1")) {
                args.set_cancel(true);
                return;
            }
        }
    }
    
  3. Check for Console Errors: Make sure to check your browser's console for any JavaScript errors that might provide more insight into the issue. If you see any specific error messages, please let me know so I can assist further.

By ensuring that any ongoing edit operations are properly closed before canceling a new edit, you can help prevent conflicts that lead to errors when interacting with other rows. If the issue persists, please provide any specific error messages from the console for further investigation.

Please refer to the following article for additional information:

Regards,
Vasko
Progress Telerik

Stay tuned by visiting our public roadmap and feedback portal pages! Or perhaps, if you are new to our Telerik family, check out our getting started resources
Richard
Top achievements
Rank 4
Iron
Iron
Iron
commented on 10 Feb 2025, 10:35 AM

Hi Vasko,

Many thanks for your reply.

I've added the get_batchEditingManager()._tryCloseEdits to my onBatchEditOpening function, and I'm still seeing the same console error "Uncaught TypeError: Cannot read properties of undefined (reading 'style')".

I've also noticed that if I don't include args.get_tableView().get_dataItems(); in the function, I get the console error "Uncaught TypeError: Cannot read properties of undefined (reading 'get_itemIndex')". 

The complete onBatchEditOpening function is:

function onBatchEditOpening(sender, args) {
    // Close any other edit cells to clear potential conflicts
    sender.get_batchEditingManager()._tryCloseEdits(sender.get_masterTableView());

    args.get_tableView().get_dataItems();
    var cell = args.get_cell();
    var cellValue = cell.innerText;
    var columnUniqueName = args.get_columnUniqueName();
    var row = args.get_row();
    var item = row.control;
    var itemIndex = item.get_itemIndex();

    if (itemIndex > -1) { // if itemIndex is -1 it means this is a new row
        if ((columnUniqueName === "Process_type" && cellValue === "L") ||
            (columnUniqueName === "Process_order" && cellValue === "1")) {
            args.set_cancel(true);
            return;
        }
    }
}

This is the main part of the grid:

<telerik:RadGrid ID="RadGridEntries" runat="server" RenderMode="Lightweight" AllowSorting="True" CellSpacing="-1" GridLines="Horizontal"
    OnNeedDataSource="RadGridEntries_NeedDataSource" OnBatchEditCommand="RadGridEntries_BatchEditCommand"
    OnItemInserted="RadGridEntries_ItemInserted" OnItemUpdated="RadGridEntries_ItemUpdated" OnItemDeleted="RadGridEntries_ItemDeleted"
    OnPreRender="RadGridEntries_PreRender" AutoGenerateColumns="false"
    AllowAutomaticUpdates="false" AllowAutomaticInserts="false" AllowAutomaticDeletes="false">
    <ClientSettings>
        <Scrolling AllowScroll="true" UseStaticHeaders="true" SaveScrollPosition="true" />
        <KeyboardNavigationSettings AllowSubmitOnEnter="false" />
        <ClientEvents OnBatchEditOpening="onBatchEditOpening" />
    </ClientSettings>
    <MasterTableView Name="Processes" AutoGenerateColumns="false" DataKeyNames="Process_id"
        CommandItemDisplay="Top" EditMode="Batch" BatchEditingSettings-OpenEditingEvent="Click" HeaderStyle-HorizontalAlign="Center">
        <CommandItemSettings ShowRefreshButton="false" />
        <BatchEditingSettings EditType="Row" HighlightDeletedRows="true" />

The PreRender is setting the max length for one of the Bound Columns.

Let me know if I can provide any further detail.

Kind regards,

Richard

Vasko
Telerik team
commented on 10 Feb 2025, 03:06 PM

Hello Richard,

Could you try replicating the behavior with the provided code snippet: 

<telerik:RadGrid ID="RadGrid1" runat="server" AllowPaging="True" Width="400px" OnNeedDataSource="RadGrid1_NeedDataSource">
    <MasterTableView AutoGenerateColumns="False" DataKeyNames="OrderID" EditMode="Batch">
        <Columns>
            <telerik:GridBoundColumn DataField="OrderID" DataType="System.Int32"
                FilterControlAltText="Filter OrderID column" HeaderText="OrderID"
                ReadOnly="True" SortExpression="OrderID" UniqueName="OrderID">
            </telerik:GridBoundColumn>
            <telerik:GridBoundColumn DataField="Process_type"
                FilterControlAltText="Filter Process_type column" HeaderText="Process Type"
                SortExpression="Process_type" UniqueName="Process_type">
            </telerik:GridBoundColumn>
            <telerik:GridBoundColumn DataField="Process_order"
                FilterControlAltText="Filter Process_order column" HeaderText="Process Order"
                SortExpression="Process_order" UniqueName="Process_order">
            </telerik:GridBoundColumn>
        </Columns>
    </MasterTableView>
    <ClientSettings>
        <ClientEvents OnBatchEditOpening="onBatchEditOpening" />
    </ClientSettings>
</telerik:RadGrid>
protected void RadGrid1_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
    (sender as RadGrid).DataSource = OrdersTable(); 
}

private DataTable OrdersTable()
{
    DataTable dt = new DataTable();

    dt.Columns.Add(new DataColumn("OrderID", typeof(int)));
    dt.Columns.Add(new DataColumn("Process_type", typeof(string)));
    dt.Columns.Add(new DataColumn("Process_order", typeof(int)));

    dt.PrimaryKey = new DataColumn[] { dt.Columns["OrderID"] };

    for (int i = 0; i < 3; i++)
    {
        int index = i + 1;

        DataRow row = dt.NewRow();

        row["OrderID"] = index;
        row["Process_type"] = index % 2 == 0 ? "L" : "N";
        row["Process_order"] = index % 2 == 0 ? 1 : 2;

        dt.Rows.Add(row);
    }

    return dt;
}
function onBatchEditOpening(sender, args) {
    args.get_tableView().get_dataItems();
    var cell = args.get_cell();
    var cellValue = cell.innerText;
    var columnUniqueName = args.get_columnUniqueName();
    var row = args.get_row();
    var item = row.control;
    var itemIndex = item.get_itemIndex();

    if (itemIndex > -1) { 
        if ((columnUniqueName === "Process_type" && cellValue === "L") ||
            (columnUniqueName === "Process_order" && cellValue === "1")) {
            args.set_cancel(true);
        }
    }
}

If possible, could you adjust the code snippet so that it reproduces the issue?

Regards,
Author nickname
Progress Telerik
Richard
Top achievements
Rank 4
Iron
Iron
Iron
commented on 10 Feb 2025, 05:00 PM

Hello Vasko,

I've managed to adjust the code snippet, and reproduce and locate the error:

<telerik:RadGrid ID="RadGrid1" runat="server" AllowPaging="True" Width="400px" OnNeedDataSource="RadGrid1_NeedDataSource"
    AllowSorting="True" CellSpacing="-1" GridLines="Horizontal" AllowAutomaticUpdates="false" AllowAutomaticInserts="false" AllowAutomaticDeletes="false"
    OnPreRender="RadGrid1_PreRender" AutoGenerateColumns="false">
    <MasterTableView Name="ProcessList" AutoGenerateColumns="False" DataKeyNames="OrderID"
        CommandItemDisplay="Top" EditMode="Batch" BatchEditingSettings-OpenEditingEvent="Click" HeaderStyle-HorizontalAlign="Center">
        <CommandItemSettings ShowRefreshButton="false" />
        <BatchEditingSettings EditType="Row" HighlightDeletedRows="true" />
        <Columns>
            <telerik:GridBoundColumn DataField="OrderID" DataType="System.Int32"
                FilterControlAltText="Filter OrderID column" HeaderText="OrderID"
                ReadOnly="True" SortExpression="OrderID" UniqueName="OrderID" Exportable="false">
            </telerik:GridBoundColumn>
            <telerik:GridTemplateColumn DataField="Process_type" SortExpression="Process_type" UniqueName="Process_type"
                HeaderText="Process Yype" FilterControlAltText="Filter Process_type column" >
                <ItemTemplate>
                    <%#DataBinder.Eval(Container.DataItem, "Process_type")%>
                </ItemTemplate>
                <EditItemTemplate>
                    <telerik:RadTextBox ID="txtProcessType" runat="server" MaxLength="2" Style="text-transform:uppercase">
                        <ClientEvents OnValueChanging="processTypeChanging" />
                    </telerik:RadTextBox>
                    <asp:RequiredFieldValidator ID="rfvProcessType" runat="server" ForeColor="Red"
                        ErrorMessage="*Process Type is required" Display="Dynamic"
                        ControlToValidate="txtProcessType" />
                    <asp:RegularExpressionValidator ID="revProcessType" runat="server" ForeColor="Red"
                        ErrorMessage="*Process Type must be up to two alpha characters" Display="Dynamic"
                        ControlToValidate="txtProcessType" ValidationExpression="^[A-Za-z]*$" />
                </EditItemTemplate>
            </telerik:GridTemplateColumn>
            <telerik:GridBoundColumn DataField="Process_order"
                FilterControlAltText="Filter Process_order column" HeaderText="Process Order"
                SortExpression="Process_order" UniqueName="Process_order">
            </telerik:GridBoundColumn>
            <telerik:GridBoundColumn DataField="Process_name"
                FilterControlAltText="Filter Process_name column" HeaderText="Process Name"
                SortExpression="Process_name" UniqueName="Process_name" MaxLength="30" ItemStyle-HorizontalAlign="Left" HeaderStyle-Width="150px">
				<ColumnValidationSettings EnableRequiredFieldValidation="true">
					<RequiredFieldValidator ForeColor="Red" Text="*Process Name is required" Display="Dynamic">
					</RequiredFieldValidator>
				</ColumnValidationSettings>
            </telerik:GridBoundColumn>
        </Columns>
    </MasterTableView>
    <ClientSettings>
        <Scrolling AllowScroll="true" UseStaticHeaders="true" SaveScrollPosition="true" />
        <KeyboardNavigationSettings AllowSubmitOnEnter="false" />
        <ClientEvents OnBatchEditOpening="onBatchEditOpening" />
    </ClientSettings>
</telerik:RadGrid>
    protected void RadGrid1_PreRender(object sender, EventArgs e)
    {
        GridTableView masterTable = (sender as RadGrid).MasterTableView;

        // Set the max length for the Bound Columns
        GridTextBoxColumnEditor processName = masterTable.GetBatchColumnEditor("Process_name") as GridTextBoxColumnEditor;
        processName.TextBoxMaxLength = 30;
    }

    protected void RadGrid1_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
    {
        (sender as RadGrid).DataSource = OrdersTable();
    }

    private DataTable OrdersTable()
    {
        DataTable dt = new DataTable();

        dt.Columns.Add(new DataColumn("OrderID", typeof(int)));
        dt.Columns.Add(new DataColumn("Process_type", typeof(string)));
        dt.Columns.Add(new DataColumn("Process_order", typeof(int)));
        dt.Columns.Add(new DataColumn("Process_name", typeof(string)));

        dt.PrimaryKey = new DataColumn[] { dt.Columns["OrderID"] };

        for (int i = 0; i < 3; i++)
        {
            int index = i + 1;

            DataRow row = dt.NewRow();

            row["OrderID"] = index;
            row["Process_type"] = index % 2 == 0 ? "L" : "N";
            row["Process_order"] = index % 2 == 0 ? 1 : 2;
            row["Process_name"] = index % 2 == 0 ? "US range" : "Non-US";

            dt.Rows.Add(row);
        }

        return dt;
    }
    function processTypeChanging(sender, args) {
        args.set_newValue(args.get_newValue().toUpperCase());
    }

    function onBatchEditOpening(sender, args) {
        args.get_tableView().get_dataItems();
        var cell = args.get_cell();
        var cellValue = cell.innerText;
        var columnUniqueName = args.get_columnUniqueName();
        var row = args.get_row();
        var item = row.control;
        var itemIndex = item.get_itemIndex();

        if (itemIndex > -1) {
            if ((columnUniqueName === "Process_type" && cellValue === "L") ||
                (columnUniqueName === "Process_order" && cellValue === "1")) {
                args.set_cancel(true);
            }
        }
    }

The error is caused by me having EditType="Row" set in BatchEditingSettings (highlighted above).  Removing it allows the grid editing to work as desired.

Kind regards,

Richard

Vasko
Telerik team
commented on 11 Feb 2025, 09:51 AM

Hi Richard,

Thank you for providing a reproducible sample code snippet.

After researching the issue more in-depth, it appears that this is a limitation of the Batch Editing mode when the EditType is set to Row. The issue stems from setting the args.set_cancel(true)  to certain cells based on the clicked cell's Column and Value,  but having other cells still be opened.

This I am afraid will not work properly with Row editing, and Cell edit type needs to be used. For the issue itself, I suggest you open a bug report on our Feedback Portal

Regards,Author nicknameProgress Telerik

Richard
Top achievements
Rank 4
Iron
Iron
Iron
commented on 13 Feb 2025, 04:43 PM

Thanks Vasko.

I'll have to stick with just cell editing for now.  I may open a bug report at a later date.

Thanks for your help,

Richard

Tags
Grid
Asked by
Richard
Top achievements
Rank 4
Iron
Iron
Iron
Answers by
Vasko
Telerik team
Share this question
or