Telerik is a leading vendor of ASP.NET AJAX, ASP.NET MVC, Silverlight, WinForms and WPF controls and components, as well as .NET Reporting, .NET ORM , .NET CMS, Code Analysis, Mocking, Team Productivity and Automated Testing Tools. Building on its expertise in interface development and Microsoft technologies, Telerik helps customers build applications with unparalleled richness, responsiveness and interactivity. Telerik products help thousands of companies to be more productive and deliver reliable applications under budget and on time.
Version Q1 2012 released 04/11/2012
select

Grid / Client Edit with Batch Server Update

Next database reset in 0 hours, 49 minutes, 56 seconds
ProductIDProductNameQuantityPerUnitUnitPriceUnitsInStockUnitsOnOrderDiscontinued
Cancel changes Process changes
Page size:
select
 64 items in 5 pages
6 Grandma's Boysenberry Spread 12 - 8 oz jars $25.00 120 0 False
7 Uncle Bob's Organic Dried Pears 12 - 1 lb pkgs. $30.00 15 0 False
10 Ikura 12 - 200 ml jars $31.00 31 0 False
12 Queso Manchego La Pastora 10 - 500 g pkgs. $38.00 86 0 False
13 Konbu 2 kg box $6.00 24 0 False
14 Tofu 40 - 100 g pkgs. $23.25 35 0 False
15 Genen Shouyu 24 - 250 ml bottles $15.50 39 0 False
16 Pavlova 32 - 500 g boxes $17.45 29 0 False
18 Carnarvon Tigers 16 kg pkg. $62.50 42 0 False
19 Teatime Chocolate Biscuits 10 boxes x 12 pieces $9.20 25 0 False
20 Sir Rodney's Marmalade 30 gift boxes $81.00 40 0 False
21 Sir Rodney's Scones 24 pkgs. x 4 pieces $10.00 3 40 False
22 Gustaf's Knäckebröd 24 - 500 g pkgs. $21.00 104 0 False
23 Tunnbröd 12 - 250 g pkgs. $9.00 61 0 False
24 Guaraná Fantástica 12 - 355 ml cans $4.50 20 0 True



  • Double-click grid cells to edit them and use the buttons in the command item template at the bottom to process or discard all changes.

Source Code

C# VB.NET
Show code in new window Demo isolation steps
  • <%@ Page Language="vb" CodeFile="DefaultVB.aspx.vb" Inherits="Telerik.GridExamplesVBNET.AJAX.ClientEditBatchUpdates.DefaultVB" %>

    <%@ Register TagPrefix="telerik" Namespace="Telerik.QuickStart" %>
    <%@ Register TagPrefix="telerik" TagName="Header" Src="~/Common/Header.ascx" %>
    <%@ Register TagPrefix="telerik" TagName="HeadTag" Src="~/Common/HeadTag.ascx" %>
    <%@ Register TagPrefix="telerik" TagName="Footer" Src="~/Common/Footer.ascx" %>
    <%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
    <%@ Register TagPrefix="sds" Namespace="Telerik.Web.SessionDS" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/tr/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <telerik:HeadTag runat="server" ID="Headtag2"></telerik:HeadTag>
    </head>
    <body class="BODY">
        <form runat="server" id="mainForm" method="post">
        <telerik:Header runat="server" ID="Header1" NavigationLanguage="VB" ShowDbResetTimer="true">
        </telerik:Header>
        <!-- content start -->
        <telerik:RadScriptManager ID="RadScriptManager1" runat="server" />
        <telerik:RadCodeBlock ID="RadCodeBlock1" runat="server">
            <script type="text/javascript">
            <!--
                //Custom js code section used to edit records, store changes and switch the visibility of column editors

                //global variables for edited cell and edited rows ids
                var editedCell;
                var arrayIndex = 0;
                var editedItemsIds = [];

                function RowCreated(sender, eventArgs) {
                    var dataItem = eventArgs.get_gridDataItem();

                    //traverse the cells in the created client row object and attach dblclick handler for each of them
                    for (var i = 1; i < dataItem.get_element().cells.length; i++) {
                        var cell = dataItem.get_element().cells[i];
                        if (cell) {
                            $addHandler(cell, "dblclick", Function.createDelegate(cell, ShowColumnEditor));
                        }
                    }
                }

                //detach the ondblclick handlers from the cells on row disposing
                function RowDestroying(sender, eventArgs) {
                    if (eventArgs.get_id() === "") return;
                    var row = eventArgs.get_gridDataItem().get_element();
                    var cells = row.cells;
                    for (var j = 0, len = cells.length; j < len; j++) {
                        var cell = cells[j];
                        if (cell) {
                            $clearHandlers(cell);
                        }
                    }
                }

                function RowClick(sender, eventArgs) {
                    if (editedCell) {
                        //if the click target is table cell or span and there is an edited cell, update the value in it
                        //skip update if clicking a span that happens to be a form decorator element (having a class that starts with "rfd")
                        if ((eventArgs.get_domEvent().target.tagName == "TD") ||
                            (eventArgs.get_domEvent().target.tagName == "SPAN" && !eventArgs.get_domEvent().target.className.startsWith("rfd"))) {
                            UpdateValues(sender);
                            editedCell = false;
                        }
                    }
                }
                function ShowColumnEditor() {
                    editedCell = this;

                    //hide text and show column editor in the edited cell
                    var cellText = this.getElementsByTagName("span")[0];
                    cellText.style.display = "none";

                    //display the span which wrapps the hidden checkbox editor
                    if (this.getElementsByTagName("span")[1]) {
                        this.getElementsByTagName("span")[1].style.display = "";
                    }
                    var colEditor = this.getElementsByTagName("input")[0] || this.getElementsByTagName("select")[0];
                    //if the column editor is a form decorated select dropdown, show it instead of the original
                    if (colEditor.className == "rfdRealInput" && colEditor.tagName.toLowerCase() == "select") colEditor = Telerik.Web.UI.RadFormDecorator.getDecoratedElement(colEditor);
                    colEditor.style.display = "";
                    colEditor.focus();
                }
                function StoreEditedItemId(editCell) {
                    //get edited row key value and add it to the array which holds them
                    var gridRow = $find(editCell.parentNode.id);
                    var rowKeyValue = gridRow.getDataKeyValue("ProductID");
                    Array.add(editedItemsIds, rowKeyValue);
                }
                function HideEditor(editCell, editorType) {
                    //get reference to the label in the edited cell
                    var lbl = editCell.getElementsByTagName("span")[0];

                    switch (editorType) {
                        case "textbox":
                            var txtBox = editCell.getElementsByTagName("input")[0];
                            if (lbl.innerHTML != txtBox.value) {
                                lbl.innerHTML = txtBox.value;
                                editCell.style.border = "1px dashed";

                                StoreEditedItemId(editCell);
                            }
                            txtBox.style.display = "none";
                            break;
                        case "checkbox":
                            var chkBox = editCell.getElementsByTagName("input")[0];
                            if (lbl.innerHTML.toLowerCase() != chkBox.checked.toString()) {
                                lbl.innerHTML = chkBox.checked;
                                editedCell.style.border = "1px dashed";

                                StoreEditedItemId(editCell);
                            }
                            chkBox.style.display = "none";
                            editCell.getElementsByTagName("span")[1].style.display = "none";
                            break;
                        case "dropdown":
                            var ddl = editCell.getElementsByTagName("select")[0];
                            var selectedValue = ddl.options[ddl.selectedIndex].value;
                            if (lbl.innerHTML != selectedValue) {
                                lbl.innerHTML = selectedValue;
                                editCell.style.border = "1px dashed";

                                StoreEditedItemId(editCell);
                            }
                            //if the form decorator was enabled, hide the decorated dropdown instead of the original.
                            if (ddl.className == "rfdRealInput") ddl = Telerik.Web.UI.RadFormDecorator.getDecoratedElement(ddl);
                            ddl.style.display = "none";
                        default:
                            break;
                    }
                    lbl.style.display = "inline";
                }
                function UpdateValues(grid) {
                    //determine the name of the column to which the edited cell belongs
                    var tHeadElement = grid.get_element().getElementsByTagName("thead")[0];
                    var headerRow = tHeadElement.getElementsByTagName("tr")[0];
                    var colName = grid.get_masterTableView().getColumnUniqueNameByCellIndex(headerRow, editedCell.cellIndex);

                    //based on the column name, extract the value from the editor, update the text of the label and switch its visibility with that of the column
                    //column. The update happens only when the column editor value is different than the non-editable value. We also set dashed border to indicate
                    //that the value in the cell is changed. The logic is isolated in the HideEditor js method
                    switch (colName) {
                        case "ProductName":
                            HideEditor(editedCell, "textbox");
                            break;
                        case "QuantityPerUnit":
                            HideEditor(editedCell, "textbox");
                            break;
                        case "UnitPrice":
                            HideEditor(editedCell, "textbox");
                            break;
                        case "UnitsInStock":
                            HideEditor(editedCell, "dropdown");
                            break;
                        case "UnitsOnOrder":
                            HideEditor(editedCell, "textbox");
                            break;
                        case "Discontinued":
                            HideEditor(editedCell, "checkbox");
                            break;
                        default:
                            break;
                    }
                }
                function CancelChanges() {
                    if (editedItemsIds.length > 0) {
                        $find("<%=RadAjaxManager1.ClientID %>").ajaxRequest("");
                    }
                    else {
                        alert("No pending changes to be discarded");
                    }
                    editedItemsIds = [];
                }
                function ProcessChanges() {
                    //extract edited rows ids and pass them as argument in the ajaxRequest method of the manager
                    if (editedItemsIds.length > 0) {
                        var Ids = "";
                        for (var i = 0; i < editedItemsIds.length; i++) {
                            Ids = Ids + editedItemsIds[i] + ":";
                        }
                        $find("<%=RadAjaxManager1.ClientID %>").ajaxRequest(Ids);
                    }
                    else {
                        alert("No pending changes to be processed");
                    }
                    editedItemsIds = [];
                }
                function RadGrid1_Command(sender, eventArgs) {
                    //Note that this code has to be executed if you postback from external control instead from the grid (intercepting its onclientclick handler for this purpose),
                    //otherwise the edited values will be lost or not propagated in the source
                    if (editedItemsIds.length > 0) {
                        if (eventArgs.get_commandName() == "Sort" || eventArgs.get_commandName() == "Page" || eventArgs.get_commandName() == "Filter") {
                            if (confirm("Any unsaved edited values will be lost. Choose 'OK' to discard the changes before proceeding or 'Cancel' to abort the action and process them.")) {
                                editedItemsIds = [];
                            }
                            else {
                                //cancel the chosen action
                                eventArgs.set_cancel(true);

                                //process the changes
                                ProcessChanges();
                                editedItemsIds = [];
                            }
                        }
                    }
                }
                window.onunload = function () {
                    //this code should also be executed on postback from external control (which rebinds the grid) to process any unsaved data
                    if (editedItemsIds.length > 0) {
                        if (confirm("Any unsaved edited values will be lost. Choose 'OK' to discard the changes before proceeding or 'Cancel' to abort the action and process them.")) {
                            editedItemsIds = [];
                        }
                        else {
                            //process the changes
                            ProcessChanges();
                            editedItemsIds = [];
                        }
                    }
                };
         -->    
            </script>
        </telerik:RadCodeBlock>
        
        <telerik:RadFormDecorator ID="RadFormDecorator1" runat="server" DecoratedControls="Default,Select,Textbox"
            EnableRoundedCorners="false" />
        <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
            <AjaxSettings>
                <telerik:AjaxSetting AjaxControlID="RadGrid1">
                    <UpdatedControls>
                        <telerik:AjaxUpdatedControl ControlID="RadGrid1" LoadingPanelID="RadAjaxLoadingPanel1" />
                        <telerik:AjaxUpdatedControl ControlID="RadInputManager1" />
                        <telerik:AjaxUpdatedControl ControlID="Label1" />
                    </UpdatedControls>
                </telerik:AjaxSetting>
                <telerik:AjaxSetting AjaxControlID="RadAjaxManager1">
                    <UpdatedControls>
                        <telerik:AjaxUpdatedControl ControlID="RadGrid1" LoadingPanelID="RadAjaxLoadingPanel1" />
                        <telerik:AjaxUpdatedControl ControlID="RadInputManager1" />
                        <telerik:AjaxUpdatedControl ControlID="Label1" />
                    </UpdatedControls>
                </telerik:AjaxSetting>
            </AjaxSettings>
        </telerik:RadAjaxManager>
        <telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" />
        <telerik:RadInputManager ID="RadInputManager1" EnableEmbeddedBaseStylesheet="false"
            Skin="" runat="server">
            <telerik:TextBoxSetting BehaviorID="StringBehavior" InitializeOnClient="true" EmptyMessage="type here" />
            <telerik:NumericTextBoxSetting BehaviorID="CurrencyBehavior" InitializeOnClient="true" EmptyMessage="type.."
                Type="Currency" Validation-IsRequired="true" MinValue="1" MaxValue="100000" />
            <telerik:NumericTextBoxSetting BehaviorID="NumberBehavior" InitializeOnClient="true" EmptyMessage="type.."
                Type="Number" DecimalDigits="0" MinValue="0" MaxValue="100" />
        </telerik:RadInputManager>
        <telerik:RadGrid ID="RadGrid1" DataSourceID="SqlDataSource1" Width="97%" ShowStatusBar="True"
            AllowSorting="True" PageSize="15" GridLines="None" AllowPaging="True" runat="server"
            AutoGenerateColumns="False">
            <MasterTableView TableLayout="Fixed" DataKeyNames="ProductID" EditMode="InPlace"
                ClientDataKeyNames="ProductID" CommandItemDisplay="Bottom">
                <CommandItemTemplate>
                    <div style="height: 30px; text-align: right;">
    <asp:Image ID="imgCancelChanges" runat="server" ImageUrl="~/Grid/Examples/DataEditing/ClientEditBatchUpdates/Img/cancel.gif"
    AlternateText="Cancel changes" ToolTip="Cancel changes" Height="24px" Style="cursor: pointer;
    margin: 2px 5px 0px 0px;" onclick="CancelChanges();" />

    <asp:Image ID="imgProcessChanges" runat="server" ImageUrl="~/Grid/Examples/DataEditing/ClientEditBatchUpdates/Img/ok.gif"
    AlternateText="Process changes" ToolTip="Process changes" Height="24px" Style="cursor: pointer;
    margin: 2px 5px 0px 0px;" onclick="ProcessChanges();" />

                    </div>
                </CommandItemTemplate>
                <Columns>
                    <telerik:GridBoundColumn UniqueName="ProductID" DataField="ProductID" HeaderText="ProductID"
                        ReadOnly="True" HeaderStyle-Width="5%" />
                    <telerik:GridTemplateColumn UniqueName="ProductName" SortExpression="ProductName"
                        HeaderText="ProductName" HeaderStyle-Width="15%">
                        <ItemTemplate>
                            <asp:Label ID="lblProductName" runat="server" Text='<%# Eval("ProductName") %>' />
                            <asp:TextBox ID="txtBoxName" runat="server" Text='<%# Bind("ProductName") %>' Width="95%"
                                Style="display: none" />
                        </ItemTemplate>
                    </telerik:GridTemplateColumn>
                    <telerik:GridTemplateColumn UniqueName="QuantityPerUnit" HeaderText="QuantityPerUnit"
                        SortExpression="QuantityPerUnit" HeaderStyle-Width="10%">
                        <ItemTemplate>
                            <asp:Label ID="lblQuantityPerUnit" runat="server" Text='<%# Eval("QuantityPerUnit") %>' />
                            <asp:TextBox ID="txtQuantityPerUnit" runat="server" Text='<%# Bind("QuantityPerUnit") %>'
                                Width="95%" Style="display: none" />
                        </ItemTemplate>
                    </telerik:GridTemplateColumn>
                    <telerik:GridTemplateColumn UniqueName="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice"
                        HeaderStyle-Width="7%">
                        <ItemTemplate>
                            <asp:Label ID="lblUnitPrice" runat="server" Text='<%# Eval("UnitPrice", "{0:C}") %>' />
                            <asp:TextBox ID="txtUnitPrice" runat="server" Width="95%" Text='<%# Bind("UnitPrice") %>'
                                Style="display: none" />
                        </ItemTemplate>
                    </telerik:GridTemplateColumn>
                    <telerik:GridTemplateColumn UniqueName="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock"
                        HeaderStyle-Width="8%">
                        <ItemTemplate>
                            <asp:Label ID="lblUnitsInStock" runat="server" Text='<%# Eval("UnitsInStock") %>' />
    <asp:DropDownList ID="ddlUnitsInStock" runat="server" DataTextField="UnitsInStock"
    DataValueField="UnitsInStock" DataSourceID="SqlDataSource2" SelectedValue='<%# Bind("UnitsInStock") %>'

                                Style="display: none" />
                        </ItemTemplate>
                    </telerik:GridTemplateColumn>
                    <telerik:GridTemplateColumn UniqueName="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder"
                        HeaderStyle-Width="7%">
                        <ItemTemplate>
                            <asp:Label ID="lblUnitsOnOrder" runat="server" Text='<%# Eval("UnitsOnOrder") %>' />
                            <asp:TextBox ID="txtUnitsOnOrder" runat="server" Text='<%# Bind("UnitsOnOrder") %>'
                                Width="95%" Style="display: none" />
                        </ItemTemplate>
                    </telerik:GridTemplateColumn>
                    <telerik:GridTemplateColumn UniqueName="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued"
                        HeaderStyle-Width="6%">
                        <ItemTemplate>
                            <asp:Label ID="lblDiscontinued" runat="server" Text='<%# Eval("Discontinued") %>' />
                            <asp:CheckBox ID="chkBoxDiscontinued" runat="server" Checked='<%# Bind("Discontinued") %>'
                                Style="display: none" />
                        </ItemTemplate>
                    </telerik:GridTemplateColumn>
                </Columns>
            </MasterTableView>
            <ClientSettings>
                <ClientEvents OnRowCreated="RowCreated" OnRowClick="RowClick" OnCommand="RadGrid1_Command"
                    OnRowDestroying="RowDestroying" />
            </ClientSettings>
        </telerik:RadGrid>
        <br />
        <asp:Label ID="Label1" runat="server" EnableViewState="false" />
        <br />
        <asp:SqlDataSource ID="SqlDataSource1" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString35 %>"
            ProviderName="System.Data.SqlClient" SelectCommand="SELECT * FROM [Products]"
            runat="server" UpdateCommand="UPDATE [Products] SET [ProductName] = @ProductName, [QuantityPerUnit] = @QuantityPerUnit, [UnitPrice] = @UnitPrice, [UnitsInStock] = @UnitsInStock, [UnitsOnOrder] = @UnitsOnOrder, [Discontinued] = @Discontinued WHERE [ProductID] = @ProductID">
            <UpdateParameters>
                <asp:Parameter Name="ProductID" Type="Int16" />
                <asp:Parameter Name="ProductName" Type="String" />
                <asp:Parameter Name="QuantityPerUnit" Type="String" />
                <asp:Parameter Name="UnitPrice" Type="Decimal" />
                <asp:Parameter Name="UnitsInStock" Type="Int16" />
                <asp:Parameter Name="UnitsOnOrder" Type="Int16" />
                <asp:Parameter Name="Discontinued" Type="Boolean" />
            </UpdateParameters>
        </asp:SqlDataSource>
        <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString35 %>"
            ProviderName="System.Data.SqlClient" SelectCommand="SELECT DISTINCT UnitsInStock FROM [Products]" />
        <!-- content end -->
        <telerik:Footer runat="server" ID="Footer1"></telerik:Footer>
        </form>
    </body>
    </html>

Get more than expected!

Take your time to truly experience the power of RadControls for ASP.NET AJAX with a free 60-day trial backed up by Telerik’s unlimited dedicated support.

Download your RadControls for ASP.NET AJAX trial and jumpstart your development with the available Getting Started resources.

If you have any questions, do not hesitate to contact us at sales@telerik.com.

Copyright 2002-2012 © Telerik. All right reserved
Telerik Inc, 201 Jones Rd, Waltham, MA 02451