Back to the index of articles and examples

Nested DataTables using RowExpansionDataTable

This example uses a variation of Eric Gelinas rowexpansion.js from YUI DataTable examples, somewhat modified by me. Here you can find the JavaScript, CSS files and the API Docs.

I start by defining some constants:

The first set are shortnames for the often used components, the second set the series of YQL queries with placeholders so that the variable part of them can be inserted via YAHOO.lang.substitute. Finally, NESTED_DT holds the property name I'll use to store each nested DataTable in the expansion state.

There are three YQLDataSource instances, here is one of them:

This one corresponds to the data fetched by the YQL_QUERY_ARTIST query. Only those fields that need some processing, like parsers, are listed, the name field, being a string, needs no parsing and doesn't need to be listed, but will be there nonetheless

Just as the DataSources are repetitive, the code to list each of the tables is also quite similar. I'll just show the one for the Album table which is the middle level. It shows both the code needed for a nested DataTable and for one containing a nested DataTable so it shows both ends.

Function showAlbums will be used as the value for the rowExpansionTemplate configuration attribute of the parent Artists table. The function will be called when any row in the parent table is expanded the first time. It will receive the state argument which contains several pieces of information regarding this expansion, amongst them the Record instance for the parent record and the container where the new table is to be built.

We immediately create the albumDT RowExpansionDataTable, using the container provided in state.expLinerEl. We don't need to define a column for the expansion trigger element, RowExpansionDataTable will create one for us. We use the corresponding YQLDataSource which we set previously: for albumDT we use albumDS.

Then we go into the configuration attributes. We assemble the initialRequest from the YQL_QUERY_ALBUMS template filling in the placeholders with the corresponding value taken from the field in the parent record: state.record.getData('id').

We also set the rowExpansionTemplate configuration attribute to showTracks, the name of the function that will create the DataTable nested to this one (the third level of nesting). We also tell the DataTable how the data will come sorted from the server, as can be seen towards the end of the YQL query.

Once the DataTable is created, we just need to do two more things. We must save this instance of the DataTable just in case, as we'll see in a moment, into the expansion state object for this row using setExpansionState. This object has several pre-defined properties but is otherwise open for us to store any extra information we might need.

We must also listen to the rowExpansionDestroyEvent because we need to destroy any nested DataTable if at any time its row in its parent DataTable gets deleted; otherwise, we would be leaving behind a lot of zombie objects taking up memory when a row is deleted. If rowExpansionTemplate had been set to a string we would not need to do this, since it won't leave anything behind.

We use the NESTED_DT property where we wisely saved the DataTable instance and call its destroy method. The DataTable we are destroying here is not the albumDT instance we have just created but the tracksDT tables that are nested to it. We always listen to this event in the parent table so we can cleanup its children. Of course it all relies on the showTracks function to store that info for each table it creates.

The Tracks DataTable is a regular DataTable since it has not further children. If I were to use the RowExpansionDataTable, the trigger column would show up, with nothing to show.