Thursday, March 29th, 2007

YUI DataTable with Row Filtering

Category: Component, Yahoo!

<p>Victor Morales was inspired by the ADO.NET disconnected data model, and it’s “Dataview” which led him to implement something similar for YUI.

He created a subclass of DataTable that allows the user to filter rows in the datatable, without the need to make another XHR call.

Row Filtering

The class YAHOO.dpu.widget.DataTable adds the “defaultView” property,
which contains a copy of the “unfiltered” RecordSet of a Datatable.

To filter rows in a DataTable you need a “RowFilter” and its
corresponding FilterAlgorithm (i.e. StringFilter), which tells the
DataTable which rows to display.

I implemented a sample RowFilter subclassing the autocomplete widget,
but it shouldn’t be too dificult to use a different implementation.

Hide Columns

To define a column as “hideable”, when creating the column object, you
have to specify the property hideable to true:

Example:

[json]
{key:”Date”, type:”date”, sortable:true, resizeable:true, hideable:true},
[/json]

To hide columns, just right-click anywhere inside the TH.

YUI Datatable

Posted by Dion Almaer at 6:38 am
11 Comments

++++-
4.4 rating from 10 votes

11 Comments »

Comments feed TrackBack URI

That works well if the DataTable only has one page …but what about paged data?

Comment by rodrigo — March 29, 2007

Yum. YUI family is just getting better and better. I really prefer it over Dojo which always seems a bit slower for me.

Comment by Liming Xu — March 29, 2007

Yes how would you handle paged data?

Really the only way would be to send a request to the server to get an updated dataset, which I think would have its benefits. For instance, you could perform the sorting in SQL, that saves some of the trouble of writing javascript code to do it client-side. But then there is the delay between sort requests now. Its a trade-off situation.

Comment by Philip Plante — March 29, 2007

Paging as implemented right now by the YUI datatable loads all the data on the initial request to an internal “RecordSet”. When you select a different page it justs alters the html to display only the rows corresponding to that page.

In theory it could be possible to make this work with paging, but the paginateRows implementation would need to be overriden/changed… (currently pagination does not alter the underlying Recordset)

Comment by Victor Andres Morales — March 29, 2007

By the way, I posted an updated example dynamically changing the row that is filtered here:
http://www.geocities.com/andresm1981/YUI-Grid/DynamicFilterDemo.htm

Also, about the issue with the current paging implementation mentioned in the post above, there is a bug request with more detailed information here:
http://sourceforge.net/tracker/index.php?func=detail&aid=1690761&group_id=165715&atid=836476

Comment by Victor Andres Morales — March 29, 2007

Paging loads all records in memory??? argh…
That will kill the browser when there are lots of rows to display.
Thats why I use Ext.

Comment by rodrigo — March 30, 2007

Great! But the column-hiding feature doesn’t work fine when there are nested headers, although I think I can work on it myself to make it work.

Comment by Ernesto — April 2, 2007

I think I got the answer to the column hiding feature to make it work with nested headers. Just substitute the original onHideMenuClick method with the one below


onhideMenuClick: function(p_sType, p_aArgs, p_oMenuItem) {
var oMenuItem = p_oMenuItem[0];
var col_no = p_oMenuItem[1];
var swap = oMenuItem.cfg.getProperty("checked");
oMenuItem.cfg.setProperty("checked", !swap);
var colstyle = swap ? 'none' : '';

var reduceHeader = function(el) {
el.colSpan--;
if (el.colSpan == 0) {
el.style.display = 'none';
}
}

var augmentHeader = function(el) {
el.colSpan++;
if (el.colSpan == 1) {
el.style.display = '';
}
}

// Initialize base headers
var oColumnSet = this.getColumnSet();
var aHeaders = oColumnSet.headers[col_no].split(' ');
var elHeader, pos = 0;
while (pos

I tested this on Firefox 2.0 only, and I have Linux, so I guess I cannot test it on IE, but I think it should work.

Comment by Ernesto — April 2, 2007

Sorry, a problem posting this (maybe you should have a “preview comment before posting” functionality?)


onhideMenuClick: function(p_sType, p_aArgs, p_oMenuItem) {
var oMenuItem = p_oMenuItem[0];
var col_no = p_oMenuItem[1];
var swap = oMenuItem.cfg.getProperty("checked");
oMenuItem.cfg.setProperty("checked", !swap);
var colstyle = swap ? 'none' : '';

var reduceHeader = function(el) {
el.colSpan--;
if (el.colSpan == 0) {
el.style.display = 'none';
}
}

var augmentHeader = function(el) {
el.colSpan++;
if (el.colSpan == 1) {
el.style.display = '';
}
}

// Initialize base headers
var oColumnSet = this.getColumnSet();
var aHeaders = oColumnSet.headers[col_no].split(' ');
var elHeader, pos = 0;
while (pos < aHeaders.length) {
elHeader = document.getElementById(aHeaders[pos]);
if (swap) {
reduceHeader(elHeader);
} else {
augmentHeader(elHeader);
}
pos++;
}

// Hide column rows
var rows = this.getBody().getElementsByTagName('tr')
for (var row = 0; row < rows.length; row++) {
var cels = rows[row].getElementsByTagName('td')
cels[col_no].style.display = colstyle;
}
}

Comment by Ernesto — April 2, 2007

Hello. This is a great feature. It works well with YUI 2.2.0 but breaks with the latest YUI release (2.2.2). Any idea what needs to be modified in the extended classes in order to get the filtering to work?

Many thanks.

Comment by Marc Stedman — April 22, 2007

@Marc:

Here is an updated tutorial using 2.2.2:
http://yuiblog.com/blog/2007/04/23/dataview/

Comment by Victor Morales — April 23, 2007

Leave a comment

You must be logged in to post a comment.