YUI Library Home

Site Search (YDN & YUIBlog):

# YUI Library Examples: DataTable Control: Filtering of Dynamic Data

This example was contributed by Wayne Fincher (a.k.a. Floydian), proprietor of PHP Horizons.

# DataTable Control: Filtering of Dynamic Data

This example, which uses server-side dynamic data, demonstrates how to filter data into a DataTable using Menu Buttons and custom-generated query strings.

This example also shows how to keep the Paginator in sync with the data loaded into the DataTable.

View example in new window.

When complex filtering of dynamic data is required, a custom `generateRequest` function is used to generate customized requests which are passed into DataSource's `sendRequest` method to populate the DataTable.

Sample Data:

{ "recordsReturned": 25, "totalRecords": 209, "startIndex": 0, "records": [ { "name": "Total population: Total", "state1": "12419293", "state2": "9938444", "state3": "8186453" }, { "name": "Total population: Male", "state1": "6080336", "state2": "4873095", "state3": "4027113" }, ... ] }

CSS:

.yui-skin-sam .yui-dt table { width: 100%; } .yui-skin-sam .yui-dt th.yui-dt-col-name { width: 301px; } .yui-skin-sam .yui-dt .yui-dt-col-state1, .yui-skin-sam .yui-dt .yui-dt-col-state2, .yui-skin-sam .yui-dt .yui-dt-col-state3 { width: 133px; text-align: right; } #containerContainer { width: 100%; height: 64px; padding: 8px 0; } #genderRadioContainer { float: left; width: 301px; } #stateSelectContainer { float: left; width: 399px; } #stateSelectContainer .yui-button button{ width: 123px; *width: 121px; _width: 118px; font-size: 85%; line-height: 1.5; } #statePaginator { text-align: center; }

Markup:

<div id="genderRadioContainer"> <p>Select a gender filter.</p> <input type="radio" name="gender" value="Both" checked> <input type="radio" name="gender" value="Female"> <input type="radio" name="gender" value="Male"> </div> <div id="stateSelectContainer"> <p>Select states to compare.</p> <input type="button" class="menuButton" id="state1" value="State 1"> <select id="state1Select"> <option value="04000US01">Alabama</option> <option value="04000US02">Alaska</option> ... </select> <input type="button" class="menuButton" id="state2" value="State 2"> <select id="state2Select"> <option value="04000US01">Alabama</option> <option value="04000US02">Alaska</option> ... </select> <input type="button" class="menuButton" id="state3" value="State 3"> <select id="state3Select"> <option value="04000US01">Alabama</option> <option value="04000US02">Alaska</option> ... </select> </div> <div id="statePaginator"><!-- The Paginator widget is rendered here --></div> <div id="stateTable"><!-- The DataTable widget is rendered here --></div>

## Customizing the `generateRequest` Function

DataTable has a default `generateRequest` function which needs to be overridden in order to create a custom query string. Keep in mind that DataTable's if column sorting is enabled, the column sort state also needs to be taken into account. Although this example does not use enable DataTable's column sorting, the comments in the code indicate integration points for that feature. Here we define a custom function, `this.requestBuilder`, to generate requests to our server that reflect the user's filtration settings:

requestBuilder: function (oState, oSelf) { /* We aren't initializing sort and dir variables. If you are using column sorting built into the DataTable, use this set of variable initializers. var sort, dir, startIndex, results; */ var startIndex, results; oState = oState || {pagination: null, sortedBy: null}; /* If using column sorting built into DataTable, these next two lines will properly set the current _sortedBy_ column and the _sortDirection_ sort = (oState.sortedBy) ? oState.sortedBy.key : oSelf.getColumnSet().keys[0].getKey(); dir = (oState.sortedBy && oState.sortedBy.dir === DataTable.CLASS_DESC) ? "desc" : "asc"; */ startIndex = (oState.pagination) ? oState.pagination.recordOffset : 0; results = (oState.pagination) ? oState.pagination.rowsPerPage : null; return "&results=" + results + "&startIndex=" + startIndex + "&state[1]=" + CF.settings.state1 + "&state[2]=" + CF.settings.state2 + "&state[3]=" + CF.settings.state3 + "&gender=" + CF.settings.gender; },

The custom function `this.requestBuilder` is then passed in as the `generateRequest` value.

// Set the DataTable configuration myConfigs = { generateRequest: this.requestBuilder ... more config settings ... };

## Sending Requests

When the user interacts with the MenuButton controls to trigger requests for filtered data, our custom `generateRequest` function provides the proper request string to DataSource's `sendRequest` method, which also requires a `callback` object.

This callback accepts four properties that are very important here.

success
failure
  There are four methods built into DataTable for handling the success and failure events. Please refer to Loading Data at Runtime for a list of the four methods and a description of each. It should suffice to say that, for this example, `onDataReturnSetRows` is what is required.
argument
  The DataTable's state -- the return value from `getState()` -- is passed as the argument value. If any changes to the Paginator UI need to be done, those changes should to be reflected in this state object. For example, if the page needs to be reset to 1, set that here and the Paginator will be updated to reflect that value when the data is returned.
scope
  Pass in your instance of the DataTable.

fireDT: function (resetRecordOffset) { var oState = CF.myDataTable.getState(), request, oCallback; /* We don't always want to reset the recordOffset. If we want the Paginator to be set to the first page, pass in a value of true to this method. Otherwise, pass in false or anything falsy and the Paginator will remain at the page it was set at before.*/ if (resetRecordOffset) { oState.pagination.recordOffset = 0; } /* If the column sort direction needs to be updated, that may be done here. It is beyond the scope of this example, but the DataTable::sortColumn() method has code that can be used with some modification. */ /* This example uses onDataReturnSetRows because that method will clear out the old data in the DataTable, making way for the new data.*/ oCallback = { success : CF.myDataTable.onDataReturnSetRows, failure : CF.myDataTable.onDataReturnSetRows, argument : oState, scope : CF.myDataTable }; // Generate a query string request = CF.myDataTable.get("generateRequest")(oState, CF.myDataTable); // Fire off a request for new data. CF.myDataSource.sendRequest(request, oCallback); }

## Handling the Response

In order to update the Paginator's `totalRecords` value as the data is returned, override the DataTable's `handleDataReturnPayload` method. This will enable the Paginator to calculate how many pages of data have been returned for each request at runtime. The rest of the work is done for us automatically through the `oCallback` object set in our `sendRequest` method call.

myDataTable.handleDataReturnPayload = function(oRequest, oResponse, oPayload) { oPayload.totalRecords = oResponse.meta.totalRecords; return oPayload; }

## Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

### DataTable Control Examples:

### More DataTable Control Resources:

- User's Guide (external)
- API Documentation
- Cheat Sheet PDF (external)

Copyright © 2010 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings