Write the jQuery code that makes the task-list application that we created in Part 1 functional
In the first part of this two-part series, published in the June 2011 issue, we developed a Windows Communication Foundation (WCF) service that takes data in and out of the Tasks table. (See " Create a Simple Task-List Application Using ASP.NET, WCF, and jQuery, Part 1.") We created a web form for displaying the tasks in a tabular format using the jQuery Templates plug-in. Finally, we developed a DatePicker plug-in to pick due dates. In this second part, we'll make the task-list application functional by writing jQuery code, including a few helper functions, code to call WCF service methods, and code to filter the task-list table.
Dealing with JSON Format
The GetJSONString() function accepts two arrays as parameters. The propertyNames array contains the property names of an object (TaskData in our case), and the propertyValues array contains their respective values. The code then iterates through the arrays and builds a string representing a JSON object. Figure 2 shows a sample TaskData object in JSON format.
Handling and Passing Dates
Calling a WCF Service from jQuery
Once our helper functions are ready, we can call the methods of the WCF service. Since we'll be calling multiple methods of the WCF service, let's encapsulate the logic in a function named CallRemoteMethod(). Figure 5 shows the complete code for the CallRemoteMethod() function.
The CallRemoteMethod() function takes three parameters: the name of the remote method to call, the parameter (if any) to the remote method, and the reference to a function that will be called when the remote method is completed. The CallRemoteMethod() function uses the ajax() method in jQuery. The ajax() method lets us make an AJAX request. A call to the ajax() method accepts several settings in key-value form. The type parameter indicates the type of request, GET or POST. The url parameter is the URL to the WCF method. Notice that the URL takes the form of <service_file_name>/<method_name>. Therefore, the URL to call the Insert() method of the service will be Service.svc/Insert.
The error handler function receives an error object that contains specifics of the error. The status property returns an error code, and statusText property returns a descriptive error message.
Handling the Ready Event
jQuery raises the ready event when the HTML Document Object Model (DOM) of a web page is completely loaded. We'll handle this event, populate the task-list table, and wire the event handlers of other controls. This way, we'll ensure that our jQuery code executes when all the elements, scripts, and variables it needs for proper functioning are loaded and accessible. Figure 7 shows the relevant code.
The first line of Figure 7 attaches the OnReady event handler to the ready event. The ready event is raised only for the document object. Many developers use anonymous functions as jQuery event handlers, such as in the following example:
Although that technique is often handy and tidy, it's better to write separate functions for the sake of readability and for ease of understanding.
Populating the Task-List Table
The OnRefresh function handles the job of populating the task-list table. Event handlers in jQuery take the event parameter that provides information about the event. Such information includes the target element that caused the event, the X and Y coordinates of the mouse, the state of the Ctrl and Shift keys, and so on. Figure 8 shows the skeleton of the OnRefresh function.
The OnRefresh method calls the CallRemoteMethod() function that we discussed earlier and passes the method name as SelectAll. The SelectAll() method doesn't take any parameter, so an empty string is passed. The third parameter of CallRemoteMethod() indicates a success function and is passed as the handler variable. The success function receives the return value of the WCF service method. The SelectAll() method returns an array of TaskData objects, so the handler function receives this array as a parameter. Figure 9 shows the complete code of the success handler function.
To populate the task-list table, we first use the remove() method in jQuery to remove all the rows of the task-data table except the header row that contains the column headings. Notice that the selector is used to select all the table rows except the first row, the header row. The first-child child filter filters the first row from all the rows of taskTable. The next siblings selector (~) returns all the rows that come after the header row. Then, we remove those rows by using the remove() method.
The tmpl() method is responsible for processing the jQuery template, and this method accepts the data to be displayed in a template. If the supplied data is in the form of an array, the template is rendered once for each element in the array. If the supplied data is an object, a single template item is rendered. Recall that taskTableContainer is our template definition. The tmpl() method returns the resultant HTML markup after processing the template. In our case, the markup will be in the form of HTML table rows. We'll then append the rows to the taskTable table by using the appendTo() method.
Next, we'll select all the Show buttons from the resultant table by using the jQuery attribute selector. An attribute selector lets us select elements based on their attribute values. We select all input elements that have the type attribute button. We attach the click event handler, which internally calls the OnSelectByID() function, to the buttons. Then, we improve the readability of the task-list table by adding different Cascading Style Sheets (CSS) classes to alternate rows. To do this, we use jQuery's :even, :odd, and :first basic filters. As the names suggest, these filters return even, odd, and first elements. The addClass() method is then used to add a CSS class to the matched elements. (You can find the complete style sheet in the code download for this article.)
Notice the use of the event.preventDefault() method in Figure 8. The Refresh button is a LinkButton control and causes postback when clicked. However, we do not need this default behavior. To cancel the postback, we call the preventDefault() method, effectively canceling the event. Figure 10 shows what the task-list table looks like when it is populated with task information.
Figure 10: The task-list table
Displaying a Selected Task for Editing
The function first stores the ID of the clicked button in a variable. Recall that the ID of a Show button is the same as the TaskID. We then apply the TaskTableSelectedRow CSS class to mark the row as selected. This way, the user gets a visual indication that the row is being edited. Notice that :has() is used in the selector to find a row that contains an input element with a specific ID. The :has() selector will select a row if it contains an element with specified criteria. Finally, we use the tmplItem() method to retrieve the data item for the row being selected. Property values of the data item are then assigned to corresponding controls by using the val() method.
Inserting, Updating, and Deleting Tasks
To insert a task, we must call the Insert() method of the WCF service. We need to retrieve values entered in various controls, form the JSON string equivalent of a TaskData object, then call the Insert() method. Figure 12 shows how this is done.
Once data is retrieved from various controls, we form a JSON string by calling the GetJSONString() function we created earlier. Arrays of property names and their values are passed to the GetJSONString() function. The CallRemoteMethod() function then invokes the Insert() method with the JSON object we just constructed. The success handler function simply sets the text of a <SPAN> element (ASP.NET Label control) to a success message and programmatically calls the click event of the Refresh button so that the newly added task will be displayed in the table.
The update operation is performed along similar lines. The only difference is that we also need to pass the TaskID as a part of the JSON object, and we need to call the Update() method. Figure 13 shows how the update operation works.
To get the TaskID of the task that is being updated, we select the table row that has the TaskTableSelectedRow CSS class applied. Only one row at a time will have this class applied. Then, from this row, we find the input element that has the type button. We need to do this checking because there is also a check box in each row. We then use the attr() method to get the ID attribute value of the button. This ID is simply the TaskID. In forming the JSON string, we use the ToWCFDate() function to convert the date selected in the DatePicker to a WCF-compliant format. Finally, the CallRemoteMethod() function is called to invoke the Update() method.
To delete one or more tasks, we need to figure out which check boxes are selected. Then, we need to call the Delete() method of the WCF service for all those TaskIDs. Figure 14 shows the OnDelete() function that is responsible for this job.
First, we use the :checked selector to select all the check boxes that are checked. Next, we need to find out the TaskID for each of the checked rows. To reach the Show button and get the TaskID, we use the parents(), find(), and each() methods. The parents() method returns all the parents for a specific element. Passing tr as a parameter to the parents() method returns only those parents that are of type tr. We then find the input element from the table row that is returned by the parents() method that has a type as button. Finally, the ID of the button is retrieved by using the attr() method, and the Delete() method of the WCF service is invoked by passing the TaskID.
The filter drop-down list lets us filter tasks that are displayed in the task-list table on the basis of their priority and status. A part of the drop-down list's change event handler is shown in Figure 15.
The code first retrieves the current selection from the filter drop-down list. If the current selection is A (All Tasks), the display CSS property of all the rows is set to block using the css() method. In this case, all the task rows in the table will be displayed.
If the current selection in the filter drop-down list is HP (High Priority), we iterate through all the data rows of the task table. With each iteration, we retrieve the data item associated with that row by using the tmplItem() method. The Priority value is then checked, and all the items with a Priority other than 1 are kept hidden by setting their display CSS property to none. Other cases of the switch statement are similar except that they check for different conditions. We won't discuss these cases in detail here.
For the correct operation of the delete functionality, we need to ensure that the task rows that are hidden don't have their check boxes selected. To do this, we filter all table rows that are hidden with the help of the :hidden selector and then remove the checked attribute from the check boxes by using the removeAttr() method.
That's it! We can now run the web form and see our task-list application in action.
In this two-part series, we developed a simple task-list application that manages tasks and their priorities, statuses, and due dates. We used a WCF service to deal with database operations, such as INSERT and UPDATE. We then invoked this WCF service from the client side by using the jQuery ajax() method. We also worked with many jQuery selectors and methods. To further improve upon what we have already developed, you can
- incorporate validations on the data that is being entered
- add visual indicators or flags for Priority and Status
- modify the DatePicker plug-in for more configuration options, or convert it into a pop-up calendar. (Note: Several ready-made plug-ins can be found on the jQuery website.)
- improve CSS classes to make the UI more appealing
Whether or not you opt for these enhancements, your task-list application is now functional and ready for action.
Bipin Joshi (email@example.com) has been programming since 1995 and has worked with .NET since its inception. He has authored or co-authored several books and numerous articles about .NET technologies. Bipin blogs about yoga and technology at bipinjoshi.com.