Several of my colleagues have been very busy recently working
on all manner of ASP.Net applications and components for use within our company.
Recently, they demonstrated a DataGrid control that they had developed that allowed
in-line editing (see the MSDN Article). After I had congratulated them on a wonderful
control, one of the team commented that this kind of functionality would not be
possible using only JavaScript—one of my favorite languages—so I decided to see
if that was the case, and this article is the story of my journey.
What Functionality do we need?
Looking at the control they had produced, I was able to identify
the following items of functionality that I needed to create to complete my challenge:
- Populate
a table with data via JavaScript. - Add sorting
functionality. - Add inline
editing functionality. - Add paging
functionality. - Add functionality
to add/delete elements.
Populating the table
To make it simple at this stage, I decided to have a single column
of data containing ten numbers and then build on that later to add more complex
data and columns. The population was relatively simple, as shown in Listing A (Demo1 in the accompanying download).
Demonstration files available for download
The demonstration files and JavaScript referred to in this
article are available in a free
download in the TechRepublic download center.
Add sorting
Now that I had the data in the table, the next thing I wanted
to do was to add sorting functionality. I based this code on my recent article on
the same topic. The resulting Demo2 can be seen in the download—a
more complex example can be found on my Web site.
Inline editing
To amend the content, I needed to be able to uniquely identify
each row and each cell in my table so that I could update their contents. To do
this, I added a <DIV> within every cell that I could reference because each
would be given a unique ID attribute. This was done very simply by modifying one
line of code as shown Listing B.
Next, I needed to add an Edit button for each Row, to do
this I decided to add a new column before the data column to hold the
“Action” buttons. This was achieved by adding the code shown in Listing C.
To keep the table in the correct shape, I also needed to add
a header cell in the table for my newly created column.
I now had a method of identifying each individual row in my table,
and an action button for it. My next challenge was creating the code to do the edit
itself. Breaking down the required functionality into its components, I ended up
with the following steps:
- Identify
the Row chosen. - Get the
current value of the Cell in that Row. - Update
the content of the Cell to include a textbox for editing and a Save and Cancel
button. - Once
the Save button is pressed, save the updated value and redisplay the table. - If the
Cancel button is pressed, reset the table to its normal state.
The first item is provided as the parameter to the editRow function called when the button is
pressed. The second can be derived either from the Cell itself, or from the Array—as
the Row number is also the Array index value. The third uses the getElementById and innerHTML methods to update the content of the specified DIV. The final
two steps are very similar to the second and third steps; I need to grab the new
value from the textbox and then convert the Cell back to a normal Cell with the
new value.
To support the inline editing functionality, I needed to create
three distinct new functions:
- An Edit
function to convert the Cell to Edit mode - A Save
function to save the changes and update the table - A Cancel
function to quit Edit mode and redisplay the table
The Edit function was relatively simple; all it needed to do
was to get hold of the cell and update its content with the textbox and the Save
and Cancel buttons. The Save function simply got the new value and assigned it to
the correct place in the array, and then repopulated the table. The Cancel function
simply repopulated the table.
To ensure that only a single row can be edited at a time, some
code was added to the Edit function to check to see if the Currently In Edit Mode
flag was set, and if so, cancel that change and then restart the new one. Code to
clear the flag was also added to the Save and Cancel functions. Combining all this
together I ended up with Demo3.
Paging
Nearing the finishing line, my next challenge was to add the
Paging functionality to the code. For this to work, we need to know two things,
which record is the current one and how many items to display per page. To make
the implementation of this slightly easier, I am going to take this in three stages:
- Basic
paging - Basic
paging with Sorting - Basic
paging with Sorting and Inline Editing
For the basic paging, we also require two new functions, one
to move forward a page and one to move back a page. For the paging, we need to
change the loop in the function that creates the cells that form the table’s
content to loop between the start and end points rather than the entire dataset.
After building the content of the table, we also need to add navigation links
to allow the user to move backwards or forwards through the data as
appropriate. This simple paging approach can be seen in Demo4.
When moving forwards or backwards through a page of data we need
to be careful of going over the bounds of the dataset. For example if we have a
page size of three elements, then our pages will show elements 1-3,4-6,7-9,10-12.
However, as our sample dataset only has 10 elements, when we hit the fourth page,
we will get an error as the code is unable to locate elements 11 and 12 of our dataset.
To resolve this, we simply add an if
statement into the loop that builds the table content to ensure that there is
an element to display. A similar issue faces us if we moving back through the data,
but this can be handled by ensuring that the value of our start location is always
a positive integer or zero, and if negative, changing it to zero.
When looking at sorting within a given page, we have several
options as to what to display when the sort has completed. We could just sort the
elements on the given page, we could sort the entire dataset and show the same page
in the newly sorted dataset, or we could go back to the first page of the dataset
and allow the user to navigate through again.
I decided on the latter of these options as it seems the most
sensible option of the three. To achieve this, we simply need to take our sorting
example Demo2 code and add a line of code to reset the start index back to zero
once the sort has completed. This ensures that the first page displayed of the sorted
data is the first n elements of the dataset. The example code for this can be found
in Demo5.
The final step is to add the inline editing to this code; this
is a simple merger of the previously created inline editing code and the paging
and sorting code we have just created. No additional code or changes are required
for this to work. An example of inline editing and paging is available in Demo6.
Adding/Deleting elements
The final challenge was to add functionality to allow me to delete
an existing element or add a new element to the dataset. Starting with the Delete
option, all we need to do is to shuffle all the elements of our dataset up one after
the deleted element and then delete the last element, as shown Table A.
The code for adding and deleting elements will be tied to an
extra button that is displayed in Edit mode for a given row. The code for this functionality
can be seen in Demo7.
That just leaves the Add row functionality, to achieve this we
will add an extra row to the table, then redisplay the DataGrid with that newly
created cell in Edit mode. When creating the extra element in the array, we need
to give it a value; to ensure that it appears last, we will give it a value of null.
However, the null appears as plain text in the appropriate place in our grid when
its row is in both Normal and Edit modes. Thus, we need to make a few small changes
to the code that generates the table—to replace it with a space when displayed in
Normal mode to keep the structure of the Table or with an empty string when in Edit
mode. Putting all of the code together results in the Demo8
file.
Possible extensions
In this article, we have successfully recreated an ASP.Net inline
editable DataGrid, using Client Side JavaScript, proving that it is possible. When
we compared both versions together, we noticed that the JavaScript version was slightly
faster than the ASP.Net approach—mainly, we believe, due to the lack of postback
required by the Javascript approach.
Some possible extensions to this functionality include the following:
- Managing
multiple columns - Adding
event handlers to check data entry, for example, numeric only, SSN, ISBN, etc. - Loading
and Saving data - Provide
specific sort routines for different datatypes - Add page
numbers to allow the user to jump to specific pages rather than moving though
each in turn - Make
some of the functionality, such as sorting and paging, optional