Infragistics Article

WebDataGrid Client-Side CRUD

Quick Summary:

Insert

Passing an array of values conforming to the schema of the data source to the add function adds data to the data source:

    $find(<GRID_CLIENT_ID>).get_rows().add(<NEW_VALUES_ARRAY>);

Delete

To remove a row, the remove function is used:

    $find(<GRID_CLIENT_ID>).get_rows().remove(<ROW_INSTANCE>,false);

Update

Updates to data in the grid are persisted by wrapping the WebDataGrid in an UpdatePanel and initiating a post back to the server.

Introduction

The WebDataGrid provides a rich API for conducting CRUD operations on the server, but many customers are not aware of the client-side API available for adding, modifying and removing rows from the data source. The key to executing these operations on the client is being aware of a few lines of JavaScript. This tutorial demonstrates how to insert, update and delete data in the grid entirely from the client.

Note: While I suggest that the CRUD operations are “entirely on the client” this label may be a bit misleading. All of the persistence is still conducted on the server, but a client-side CRUD approach endeavors to send persistence messages to the server using Ajax instead of requiring a full post back to the server. Further, the client-side CRUD method alleviates the need to write code behind in order to interact with the data source.

Consider a page that has a grid and a few other controls available to the user:

WebDataGrid with controls for client CRUD

The WebDataGrid is responsible for displaying data in the standard manner. Deleting a row from the grid (and subsequently the data source) is a simple matter of clicking on the row selector and pressing the Delete button. Updates to the grid’s data are made in-line in the grid and are not instantly saved. The grid allows you to edit as many fields as you wish and changes are persisted by clicking the Update button. Finally, data is added to the data source by entering the required data and then clicking the Add button.

Note: The WebDataGrid features some default controls which provide an interface to add data to the grid. Using the blank row at the bottom of the grid will by default use an Ajax request to add data to the source, but the purpose of this article is to demonstrate how to use input controls that are disconnected from the grid to insert data.

WebDataGrid default controls for adding a new row to the data source

Be sure to download the code here to step through the code on your own.

The Markup

The markup for this sample includes a number of different controls which are discussed in sections. The first group of controls on the page are the WebDataGrid and UpdatePanel.

WebDataGrid and UpdatePanel

The markup for this sample begins with the traditional inclusion of the ScriptManager and the WebDataGrid. A small twist to this sample is the use of an UpdatePanel that surrounds the grid and a few button controls.

The WebDataGrid features a pay-to-play model where the scripts and other resources required by the grid for it’s rich features are only served to the client if the behaviors are enabled. Therefore examine the below screenshot of the behaviors editor to get an idea of the behaviors required to execute client CRUD.

WebDataGrid with controls for client CRUD

Enabling Cell Editing, Row Adding and Row Deleting ensures the script files needed to enable these behaviors on the grid are served to the client. The Row Selectors behaviors is enabled to provide a place to the user to select an entire row, which is required to remove a row. Finally, the Selection behavior is needed to format how the row selection is conducted. In this case when a cell or the row selector is clicked, the entire row is selected. Selecting the whole row is necessary so the grid will fire the RowSelectionChanged event, which in this case is handled by the onRowSelectionChanged function. This function provides the hooks needed to programmatically locate selected row.

To see how all these settings translate into markup, here is the UpdatePanel and grid markup for the page:

<asp:UpdatePanel runat="server">
    <ContentTemplate>
        <ig:WebDataGrid 
            ID="wdg" 
            runat="server" 
            AutoGenerateColumns="False" 
            DataSourceID="ods"
            DataKeyFields="Id" 
            Width="400">
            <Columns>
                <ig:BoundDataField 
                    DataFieldName="FirstName" 
                    Header-Text="First Name" 
                    Key="FirstName" />
                <ig:BoundDataField 
                    DataFieldName="LastName" 
                    Header-Text="Last Name" 
                    Key="LastName" />
            </Columns>
            <Behaviors>
                <ig:EditingCore>
                    <Behaviors>
                        <ig:CellEditing />
                        <ig:RowAdding />
                        <ig:RowDeleting />
                    </Behaviors>
                </ig:EditingCore>
                <ig:Selection 
                    CellClickAction="Row" 
                    RowSelectType="Single">
                    <SelectionClientEvents 
                        RowSelectionChanged="onRowSelectionChanged" />
                </ig:Selection>
                <ig:RowSelectors>
                </ig:RowSelectors>
            </Behaviors>
        </ig:WebDataGrid>
        <input type="button" value="Delete" onclick="del();" />
        <asp:Button Text="Update" runat="server" />
    </ContentTemplate>
</asp:UpdatePanel> 

ObjectDataSource

An ASP.NET data source control is required to provide an interface for the WebDataGrid to access the application’s persistence mechanisms. This sample uses the ObjectDataSource, but you may use any other data source control for your purposes.

The data source control points to the matching methods off a class named PersonRepository to delegate the work of persisting changes:

<asp:ObjectDataSource 
    ID="ods" 
    runat="server" 
    DataObjectTypeName="Person" 
    DeleteMethod="Delete" 
    InsertMethod="Insert" 
    SelectMethod="GetAll" 
    TypeName="PersonRepository" 
    UpdateMethod="Update" 
    onobjectcreating="ods_ObjectCreating">
    <DeleteParameters>
        <asp:Parameter Name="id" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

Notice the event handler for onobjectcreating. This event handler is used in order to provide the data source control with a single instance of the PersonRepository class, rather than a new instance being created upon each operation of the data source control. There are a few lines of code in the code behind in order to provide the control with it’s object instance:

using System;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
    private WebStateRepository<personrepository> _repository = 
        new WebStateRepository<personrepository>();

    protected void ods_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
    {
        e.ObjectInstance = this._repository.Instance;
    }

    protected void Page_PreRender(object sender, EventArgs e)
    {
        if (this.Page.IsPostBack)
        {
            this._repository.Persist();
        }
    }
}

The important part of this code listing is in the body of the ods_ObjectCreating method. This is where you give the ObjectDataSource control the instance of the object you want to use.

Note: The WebStateRepository class is a utility class used in this sample to store the object collection in session state. In your implementation, you will simply point the data source control to an instance of your real repository class.

HTML Input Controls

The listing below demonstrates the markup required to render the text boxes which give the user a place to enter the new person’s first and last name. When the Add button is clicked, a JavaScript function named add is run on the page.

<div>
    <input type="text" id="firstName" name="firstName" />
    <input type="text" id="lastName" name="lastName" />
    <input type="button" value="Add" onclick="add();" /> 
</div>

The Script

Up to this point all the code in this article should be relatively familiar to you. The last step required is to wire up the client-side messages to add and delete data. (Remember updates are sent to the server in a batch by changing data in-line in the grid and initiating a post back to the server inside an UpdatePanel)

Add Data

function add() {
    var grid = $find("<%= wdg.ClientID %>");
    var rows = grid.get_rows();
    var newPerson = [$get("firstName").value, $get("lastName").value];
    rows.add(newPerson);
}

To send the insert request to the server all that is required is to pass an array of the new values to the add function off the rows collection. This function uses the ASP.NET Ajax selectors to find the firstName and lastName controls on the page and create a new array based on the values in the controls. To commit the insert, the array is passed to the add function.

Delete Data

Deleting data is a two step process. First the user must select which row is marked for deletion. Once the selected row is located, then the row may be removed. To handle the selection process the RowSelectionChanged event calls the onRowSelectionChanged function:

var selectedDataKey = "";

function onRowSelectionChanged(sender, eventArgs) {
    var rows = eventArgs.getSelectedRows();
    var selectedRow = rows.getItem(0);
    selectedDataKey = selectedRow.get_dataKey();
}

First the selectedDataKey variable is created to store the selected key found when the row selection is changed. The onRowSelectionChanged function interrogates the eventArgs for the selected rows. Earlier the grid was configured to only allow single selection of rows, so the selectedRow variable gets its values safely by calling row.getItem(0). Finally the value for the selectedDataKey comes from calling the get_dataKey() function of the selectedRow instance.

Now that the selected key is a known value the key is used to commit a delete to the data source:

function del() {
    if (selectedDataKey != "") {
        var grid = $find("<%= wdg.ClientID %>");
        var rows = grid.get_rows();
        var row = rows.get_rowFromKey(selectedDataKey);
        rows.remove(row, false);
    }
    else {
        alert("Please select a row to remove.");
    }
}

From an instance of the grid’s rows collection the get_rowFromKey method will find the single row selected earlier by the user. Passing the row instance to the row collection’s remove function sends a delete message to the server. The second argument of the remove method is a bit unintuitive. The argument name is noncommitting:

WebDataGrid with controls for client CRUD

Therefore if you want to commit the change to the data source, you must pass in a false to the function.

Resources

Recent Comments

By: kfiduk Posted on 10-07-2011 4:05 PM

Can you explain exactly why it's necessary to manually assign the ObjectContext to an instance of WebStateRepository?  Does the repository live on the session object or something?  I don't see how the manual assignment is preventing a new instantiation of WebStateRepository -- which occurs anyhow as you're newing it up as part of the Page property.

It's probably WebForms magic behind the scenes -- is the page using a ViewState or something?

By: Abhishek Posted on 10-07-2011 8:54 AM

I have tried adding the row it Adds a duplicate row with the same name, i.e. if i try to add XYZ it will add XYZ twice, Kindly let me know am I missing something.

Thanks in Advance

ABhishek

By: workmama Posted on 06-02-2011 6:03 PM

Craig -

What version of the WebDataGrid does this example apply to? I am using 2010.v3 and I am not seeing some of the events and attributes in my code that are in this example.

Thanks,

Matt

By: klp0 Posted on 07-07-2010 10:07 AM

Hi Craig,

Thanks for the tutorial!  I would like to know if this is possible for a table with a composite key?  Does the Datakeyfield allow two columns to represent the key? would appreciate any help you can give.  Thanks!

Kavita

By: zhq442577358 Posted on 04-01-2010 11:14 AM

1 ,hao to use tabKey get the ultrawebgrid on focus and  selected first row???

2,  ultrawebgrid row is selected,  hao to disable tab key select next Row??  I think  use tab key to focus on pages next tabindex control

By: jcrumley Posted on 02-04-2010 9:01 PM

Hi Craig!

This article/video/download was very helpful in clearing up some issues I was having using the webdatagrid for the first time.  I have run into a problem when expanding upon the ClientCRUD project I would appreciate your thoughts on.  I added a drop down editor to the grid (following another example from demos) and a templatedatacolumn.  The editor is bound to an object data source.  It blows up with an error about the controls collection can not be modified during certain pages of the page life (all the details are in case CAS-39620-UVB20L which "awaiting assignment").

In general, is there any reason that template data column + ODS + drop down column should not work?

Thanks,

John

Sign in to post a comment to this article.