DataTable and supporting modules were rebuilt in version 3.5.0. The new architecture is not fully backward compatible with versions 3.4.1 and prior. This guide is to help answer questions that may come up when upgrading to the latest version.
This guide focuses on 3.4.1 API compatibility. It does not describe new features added in 3.5.0 (there were a lot). Refer to the updated DataTable user guide for that.
If you are unable to upgrade due to unresolvable issues, you can use the
datatable-deprecated
module suite, which is equivalent to the 3.4.1 implementation. But be
aware that these modules will be removed in a future version of YUI.
The architectural change resulted in the deprecation, replacement, or removal of nearly all attributes and properties from the version 3.4.1 implementation. Here is a quick list of the changes most likely to affect your upgrade:
new Y.DataTable.Base(...)
→
new Y.DataTable({ ... })
new Y.DataTable.Base({ columnset: [ ... ], recordset: [ ... ] });
→
new Y.DataTable({ columns: [ ... ], data : [ ... ] });
columns: [ { key: 'email', allowHTML: true }, ... ]
table.plug(Y.Plugin.DataTableSort)
→ (plugin not needed)
See below or read
the user guide
table.plug(Y.Plugin.DataTableScroll, ...)
→
(plugin not needed)
See below or read
the user guide
columnset: [ { formatter: function (o) { ... } } ]
→
(formatter changes)
See below or read
the user guide
record.getValue(fieldName)
→
record.get(fieldName)
As of 3.5.0, Y.DataTable
is no longer just a namespace, but is now the
preferred constructor for DataTable instances.
var table = new Y.DataTable({ // Column configuration looks much the same except the attribute name columns: [ { key: 'name', label: 'Name', sortable: true, width: '200px' }, { key: 'birthdate', label: 'Age', sortable: true, formatter: function (o) { var now = new Date(), years = now.getYear() - o.value.getYear(); now.setYear(o.value.getYear()); return years - (o.value < now); } } ], // Passing in row data looks much the same except the attribute name data: [ { name: 'Tom Brokaw', birthdate: new Date(1940, 1, 6) }, { name: 'Peter Jennings', birthdate: new Date(1938, 6, 29) }, { name: 'Katie Couric', birthdate: new Date(1957, 1, 7) }, { name: 'Brian Williams', birthdate: new Date(1958, 4, 5) }, { name: 'Matt Lauer', birthdate: new Date(1957, 11, 30) } ] }).render('#over-there');
The Y.DataTable.Base
class still exists, but is useful primarily as a
superclass for extension. The attributes of Y.DataTable.Base
are the
same as those of Y.DataTable
, less any attributes added by class
extensions (see below).
Configuration attributes that have changed from 3.4.1 are:
Attribute | Change |
---|---|
columnset |
Deprecated. Use columns . columnset will
behave as an alias for columns for a short time, but will be
removed in future versions. See below.
|
recordset |
Deprecated. Use data . recordset will
behave as an alias for data for a short time, but will be
removed in future versions. See below.
|
tdValueTemplate |
Removed. Use column formatter , cellTemplate ,
or override the Y.DataTable.BodyView instance's CELL_TEMPLATE .
|
thValueTemplate |
Removed. Use column label , headerTemplate ,
or override the Y.DataTable.HeaderView instance's CELL_TEMPLATE .
|
trTemplate |
Removed. Use column nodeFormatter or override
the Y.DataTable.BodyView instance's ROW_TEMPLATE .
|
The following changes apply to table and column cell formatting:
allowHTML: true
to the column
configuration. HTML is escaped by default for security.
o.classnames
in the formatter parameter is now o.className
.
o.column
in the formatter parameter is now the
plain JavaScript object containing the column configurations rather
than a Y.Column
instance.
o.record
in the formatter parameter is now a Model
instance instead of a Y.Record
instance.
this.createCell(o)
, o.td
, o.tr
, and o.tbody
no longer exist on
the parameter passed to formatter
functions. Use
nodeFormatter
s.
o.headers
is now at o.column._headers
, but is read-only for
formatter
functions. If you need to change the cell's headers
attribute, add a {placeholder} for them to a custom cellTemplate
for
the column, or use a nodeFormatter
.
tdValueTemplate
, thValueTemplate
, and trTemplate
no
longer exist, nor do the DataTable instance properties tdTemplate
and
thTemplate
. Use formatter
strings or functions to customize the
content of data cells in a column and label
strings to customize the
content of header cells. To modify the <td>
or <th>
entirely, set
the column configuration cellTemplate
or headerTemplate
.
var table = new Y.DataTable.Base({ columnset: [ { key: "id", emptyCellValue: "<em>new</em>" }, { key: "name" }, { key: "price", formatter: "${value}" }, { key: "price", formatter: function (o) { if (o.value > 4) { o.classnames += "spendy"; } return '$' + o.value.toFixed(2); } }, { key: "price", formatter: function (o) { var cell = this.createCell(o); if (o.value > 4) { cell.addClass('spendy'); } cell.setHTML('$' + o.value); } } ], data: [ { id: 1, name: "Bread", price: 3.45 }, { id: 2, name: "Milk", price: 4.99 }, { id: 3, name: "Eggs", price: 2.75 } ] }).render("#over-there");
var table = new Y.DataTable({ columns: [ { key: "id", emptyCellValue: "<em>new</em>", allowHTML: true }, { key: "name" }, { key: "price", formatter: "${value}" }, { key: "price", formatter: function (o) { if (o.value > 4) { o.className += "spendy"; } return '$' + o.value.toFixed(2); } }, { key: "price", nodeFormatter: function (o) { if (o.value > 4) { o.cell.addClass('spendy'); } o.cell.setHTML('$' + o.value); return false; } } ], data: [ { id: 1, name: "Bread", price: 3.45 }, { id: 2, name: "Milk", price: 4.99 }, { id: 3, name: "Eggs", price: 2.75 } ] }).render("#over-there");
Read the Formatting Cell Data section in the DataTable user guide for more details.
As of 3.5.0, the Y.Columnset
and Y.Column
classes have been deprecated.
The DataTable configuration attribute columnset
has been deprecated in
favor of the columns
attribute. The columnset
attribute has been
retained for partial backward compatibility. Columns are now
stored as an array of simple JavaScript objects rather than class instances.
var table = new Y.DataTable({ columnset: [ 'name', 'age' ], ... }); // columnset passes through to columns var columns = table.get('columns'); // => Array, not Columnset instance table.set('columnset', [ ... (new column configurations) ... ]); // backward compatibility stops here var columnset = table.get('columnset'); // => Array, not Columnset instance
Strings passed into the column configuration will become objects with those
strings as the value of the key
property.
See the Column configuration section in the user guide for more details.
As of 3.5.0, DataTable uses Y.Model
and Y.ModelList
to store row data.
Y.Recordset
and Y.Record
haven't been deprecated, but may be in the
future. The recordset
attribute has been retained for partial
backward compatibility. The data
ModelList can be assigned to, but
retrieving the value of the attribute will return the ModelList, not
a Y.Recordset
instance.
var table = new Y.DataTable({ columnset: [ ... ], recordset: [ { name: 'Tom Brokaw', birthdate: new Date(1940, 1, 6) }, { name: 'Peter Jennings', birthdate: new Date(1938, 6, 29) }, { name: 'Katie Couric', birthdate: new Date(1957, 1, 7) }, ... ] }); // recordset passes through to data. var data = table.get('data'); // => ModelList instance table.set('recordset', [ ... (new data records) ... ]); // backward compatibility stops here var recordset = table.get('recordset'); // => ModelList, not Recordset
Y.Record
stores all values in a single attribute named data
, where Y.Model
uses individual attributes for each value.
// Y.Record var record = oldTable.get('recordset').item(0); record.getValue('birthdate'); // => Date(1940, 1, 6) record.get('data').birthdate; // => same
// Y.Model var model = newTable.getRecord(0); model.get('birthdate'); // => Date(1940, 1, 6)
This change breaks column/record keys that contain periods.
Attribute treats periods as subproperty indicators, so periods are no
longer allowed; use an alternate character. In the case of remote data
that is parsed by Y.Plugin.DataSourceJSONSchema
, use the locator
configuration for fields to extract subproperty values. A benefit to doing
this is that you may not need to specify a column label
.
var table = new Y.DataTable.Base({ columnset: [ { key: "id" }, { key: "Product.Name", label: "Product" }, { key: "Product.Price", label: "Price" } ], caption: "Price List" }).plug(Y.Plugin.DataTableDataSource, { datasource: new Y.DataSource.IO({ source: "/service/price-list" }).plug(Y.Plugin.DataSourceJSONSchema, { schema: { resultListLocator: "items", resultFields: [ { key: "id" }, { key: "Product.Name" }, { key: "Product.Price" } ] } }) }); table.datasource.load(...);
var table = new Y.DataTable({ columns: [ "id", "Product", "Price" ], caption: "Price List" }).plug(Y.Plugin.DataTableDataSource, { datasource: new Y.DataSource.IO({ source: "/service/price-list" }).plug(Y.Plugin.DataSourceJSONSchema, { schema: { resultListLocator: "items", resultFields: [ { key: "id" }, { key: "Product", locator: "Product.Name" }, { key: "Price", locator: "Product.Price" } ] } }) }); table.datasource.load(...);
If you are using any Recordset plugins, your code will need to be modified. Some loss of functionality may result.
Y.Plugin.RecordsetSort
Y.Plugin.DataTableSort
plugin
to the DataTable's Recordset instance. Sorting is now enabled
through a class extension.
Y.Plugin.RecordsetFilter
filter(function)
method. If you were relying on this plugin's grep
or reject
methods or the filter(key, value)
functionality, you will need to
replace that functionality through custom code.
Y.Plugin.RecordsetIndexer
id
(or another,
assigned primary key attribute) and clientId
. See
the Model user guide for more
information on customizing the primary index. If multiple custom
indexes are required, DataTable supports the use of
custom Model subclasses to store the record
data.
See the Data Configuration section of the DataTable user guide for more information.
The two optional features available for DataTable in 3.4.1 were sorting and
scrolling. Both features exist in 3.5.0, but are implemented as class
extensions for Y.DataTable
. Simply including the datatable-sort
or
datatable-scroll
module in your use(...)
will enable the feature for
all new DataTables.
YUI().use('datatable-sort', 'datatable-scroll', function (Y) { // Create a DataTable that is sortable by the "name" column, and is // configured to scroll vertically within 300px. Because scrollable is // set to "y", not "x" or "xy", it will not attempt to scroll horizontally. // Instead the table width will be set to 100%. var table = new Y.DataTable({ columns : [ { key: 'name', sortable: true }, ... ], data : [ ... ], scrollable: "y", height : "300px", width : "100%" }); // No plugins necessary table.render('#over-there'); });
Configuring sortable columns may be done as it was in 3.4.1, by setting the
column configuration property sortable: true
, but may also be done by
setting the DataTable's sortable
configuration to true
or an array of
column names.
// Assumes use('datatable-sort') or use('datatable') var table = new Y.DataTable.Base({ columnset: [ { key: "id" }, { key: "name", sortable: true }, { key: "price", sortable: true } ], recordset: [ { id: 1, name: "Bread", price: 3.45 }, { id: 2, name: "Milk", price: 4.99 }, { id: 3, name: "Eggs", price: 2.75 }, ... ], caption: "Price List" }); table.plug(Y.Plugin.DataTableSort); table.render('#sort-demo'); // Sorting API is on the Recordset's plugin table.get("recordset").sort.sort("name");
// Assumes use('datatable-sort') or use('datatable') var table = new Y.DataTable({ columns: [ "id", "name", "price" ], data: [ { id: 1, name: "Bread", price: 3.45 }, { id: 2, name: "Milk", price: 4.99 }, { id: 3, name: "Eggs", price: 2.75 }, ... ], sortable: [ "name", "price" ] }); table.render('#sort-demo'); // Sort method is on the instance table.sort("name"); //------------------------------------------------- // Alternate methods //------------------------------------------------- var table = new Y.DataTable({ columns: [ "id", "name", "price" ], data: [ ... ], sortable: true // makes all columns sortable }); // OR the old way works, too var table = new Y.DataTable({ columns: [ { key: "id" }, { key: "name", sortable: true }, { key: "price", sortable: true } ], data: [ ... ] });
Since there is no plugin, the sort
method is now on the DataTable instance
itself, as are the related attributes. In particular, the lastSortedBy
attribute from the plugin implementation has been replaced by the sortBy
attribute added by the class extension.
As of 3.5.0, DataTables configured with sortBy
will have their rows
sorted automatically upon inserting into the table. You do not need to
presort data for the initial render.
The trigger
attribute of the sorting plugin was not retained in
the 3.5.0 class extension. If you require an alternate triggering
event, detach and replace the table's _sortHandle
property after
render()
.
var table = new Y.DataTable({ ... }).render("#over-there"); table._sortHandle.detach(); table._sortHandle = table.delegate(["dblclick", "keydown"], table._onUITriggerSort, ".yui3-datatable-sortable-column", table);
See the Column Sorting section of the user guide for details about the APIs and attributes.
Like sorting, the scrolling functionality has been moved to a class
extension, making it unnecessary to plug the DataTable instance with the
(now deprecated) Y.Plugin.DataTableScroll
plugin.
datatable-scroll
is no longer included in the datatable
rollup, and must be explicitly included in your use()
statement.
To enable scrolling in 3.5.0, set the table's scrollable
attribute to "x",
"y", or "xy". The configured height
and width
for the DataTable are
used to bound the overall widget dimesions. Scrolling will only be applied
on the axis or axes specified in scrollable
. However, if scrollable
is
set to "y", but the height
isn't set, it will not be made scrollable.
Likewise for "x" and width
.
// Assumes use("datatable-scroll") or use("datatable") var table = new Y.DataTable.Base({ columnset: ["id", "name", "price"], recordset: [ { id: 1, name: "Bread", price: 3.45 }, { id: 2, name: "Milk", price: 4.99 }, { id: 3, name: "Eggs", price: 2.75 }, ... ] }); table.plug(Y.Plugin.DataTableScroll, { height: "175px" }); table.render("#over-there");
// Assumes use("datatable-scroll") var table = new Y.DataTable({ columns: ["id", "name", "price"], data: [ { id: 1, name: "Bread", price: 3.45 }, { id: 2, name: "Milk", price: 4.99 }, { id: 3, name: "Eggs", price: 2.75 }, ... ], scrollable: "y", height: "175px" }).render("#over-there");
DataTable in 3.5.0 applies more CSS classes to Nodes, stamps fewer nodes
with guid ids, and does not render header and cell liner <div>
s.
Below are examples of the same table rendered in 3.4.1 and 3.5.0. The 3.5.0 table has comments indicating markup added by feature modules.
<div id="(guid)" class="yui3-widget yui3-datatable"> <div id="(guid)" class="yui3-datatable-content"> <table> <caption> Example table with simple columns </caption> <colgroup> <col> <col> <col> </colgroup> <thead class="yui3-datatable-columns"> <tr id="" class="yui3-datatable-first yui3-datatable-last"> <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-id" abbr=""> <div class="yui3-datatable-liner"> id </div> </th> <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-name" abbr=""> <div class="yui3-datatable-liner"> name </div> </th> <th id="(guid)" rowspan="1" colspan="1" class="yui3-column-price" abbr=""> <div class="yui3-datatable-liner"> price </div> </th> </tr> </thead> <tbody class="yui3-datatable-msg"> </tbody> <tbody class="yui3-datatable-data" id="(guid)"> <tr id="(guid)" class="yui3-datatable-even"> <td headers="(guid)" class="yui3-column-id"> <div class="yui3-datatable-liner"> 1 </div> </td> <td headers="(guid)" class="yui3-column-name"> <div class="yui3-datatable-liner"> Bread </div> </td> <td headers="(guid)" class="yui3-column-price"> <div class="yui3-datatable-liner"> 3.45 </div> </td> </tr> <tr id="(guid)" class="yui3-datatable-odd"> <td headers="(guid)" class="yui3-column-id"> <div class="yui3-datatable-liner"> 2 </div> </td> <td headers="(guid)" class="yui3-column-name"> <div class="yui3-datatable-liner"> Milk </div> </td> <td headers="(guid)" class="yui3-column-price"> <div class="yui3-datatable-liner"> 4.99 </div> </td> </tr> <tr id="(guid)" class="yui3-datatable-even"> <td headers="(guid)" class="yui3-column-id"> <div class="yui3-datatable-liner"> 3 </div> </td> <td headers="(guid)" class="yui3-column-name"> <div class="yui3-datatable-liner"> Eggs </div> </td> <td headers="(guid)" class="yui3-column-price"> <div class="yui3-datatable-liner"> 2.75 </div> </td> </tr> </tbody> </table> </div> </div>
<div id="(guid)" class="yui3-widget yui3-datatable"> <div id="(guid)" class="yui3-datatable-content"> <table cellspacing="0" class="yui3-datatable-table" id="(guid)"> <caption class="yui3-datatable-caption"> Price List </caption> <!-- colgroup only renders if datatable-column-widths is use()d. Note, datatable-column-widths is included in the datatable rollup --> <colgroup id="(guid)"> <col> <col> <col> </colgroup> <thead class="yui3-datatable-columns" id="(guid)"> <tr> <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-first-header yui3-datatable-col-id" scope="col" data-yui3-col-id="id"> id </th> <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-col-name" scope="col" data-yui3-col-id="name"> name </th> <th id="(guid)" colspan="1" rowspan="1" class="yui3-datatable-header yui3-datatable-col-price" scope="col" data-yui3-col-id="price"> price </th> </tr> </thead> <!-- The message tbody only renders if datatable-message is use()d. Note, datatable-message is included in the datatable rollup --> <tbody class="yui3-datatable-message" id="(guid)"> <tr> <td class="yui3-datatable-message-content" colspan="3"> No data to display </td> </tr> </tbody> <tbody class="yui3-datatable-data"> <tr id="(guid)" data-yui3-record="record_1" class="yui3-datatable-even"> <td class="yui3-datatable-col-id yui3-datatable-cell"> 1 </td> <td class="yui3-datatable-col-name yui3-datatable-cell"> Bread </td> <td class="yui3-datatable-col-price yui3-datatable-cell"> 3.45 </td> </tr> <tr id="(guid)" data-yui3-record="record_2" class="yui3-datatable-odd"> <td class="yui3-datatable-col-id yui3-datatable-cell"> 2</td> <td class="yui3-datatable-col-name yui3-datatable-cell"> Milk </td> <td class="yui3-datatable-col-price yui3-datatable-cell"> 4.99 </td> </tr> <tr id="(guid)" data-yui3-record="record_3" class="yui3-datatable-even"> <td class="yui3-datatable-col-id yui3-datatable-cell"> 3 </td> <td class="yui3-datatable-col-name yui3-datatable-cell"> Eggs </td> <td class="yui3-datatable-col-price yui3-datatable-cell"> 2.75 </td> </tr> </tbody> </table> </div> </div>
Obviously, there were a lot of changes to DataTable from 3.4.1 to 3.5.0. It's entirely likely that I have missed something here. If you experience trouble with your upgrade and find this migration guide is missing something important, please file a ticket and I'll update it as soon as possible.
Additional resources to help with the upgrade include the forums, and the #yui IRC channel on freenode.net.