index.mustache revision 9533104fb7447a0765dc2aafec105c729d2c1be7
<style type="text/css">
.yui3-datatable table {
width: auto;
}
.yui3-datatable td, .yui3-datatable th {
border: 0 none;
}
</style>
<div class="intro component">
<p>
The DataTable widget is responsible for rendering columnar data into a
highly customizable and fully accessible HTML table. The core
functionality of DataTable is to visualize structured data as a table.
A variety of class extensions can then be used to add features to the
table such as sorting and scrolling.
</p>
</div>
{{>getting-started}}
<h2 id="using">Using DataTables</h2>
<h3 id="basics">DataTable basics</h3>
<p>
A basic DataTable is comprised of columns and rows. Define the columns you
want to display in your DataTable with the `columns` attribute. Rows are
created for you based on the data you provide to the `data` attribute.
Under the hood, the DataTable class uses a ModelList instance to manage the
row data properties.
</p>
```
// Columns must match data object property names
var data = [
{ id: "ga-3475", name: "gadget", price: "$6.99", cost: "$5.99" },
{ id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
{ id: "wi-0650", name: "widget", price: "$4.25", cost: "$3.75" }
];
var table = new Y.DataTable({
columns: ["id", "name", "price"],
data: data,
// Optionally configure your table with a caption
caption: "My first DataTable!",
// and/or a summary (table attribute)
summary: "Example DataTable showing basic instantiation configuration"
});
table.render("#example1");
```
<p>This code produces this table:</p>
<div id="example1" class="yui3-skin-sam"></div>
<script>
YUI().use('datatable-base', function (Y) {
// Columns must match data object property names
var data = [
{ id: "ga-3475", name: "gadget", price: "$6.99", cost: "$5.99" },
{ id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
{ id: "wi-0650", name: "widget", price: "$4.25", cost: "$3.75" }
];
var table = new Y.DataTable({
columns: ["id", "name", "price"],
data: data,
caption: "My first DataTable!",
summary: "Example DataTable showing basic instantiation configuration"
});
table.render("#example1");
});
</script>
<h3 id="columns">Working with columns</h3>
<p>
The `columns` attribute is an array of field names that correspond to
property names in the `data` objects. These field names are called "keys".
As long as these keys exist in your data, DataTable will display these
columns in the table.
</p>
<p>
For greater flexibility, columns can also be identified with configuration
objects. When identifying a column with a configuration object, use the
`key` property to reference the column name string. Otherwise, these
objects let you customize how your data renders in many ways, depending on
which table extensions or plugins you have included.
</p>
<p>
Here's an example of a `columns` setup using a number of other configurations:
</p>
```
// The attr attribute enhances the screen-reader experience
var cols = [
{
// The key relates this column to a data field
key: "mfr-parts-database-id",
// The label is the text that will be rendered in the table head
label: "Mfr Part ID",
// The abbr sets the <th>s abbr attribute
abbr: "ID"
},
{
key: "mfr-parts-database-name",
label: "Mfr Part Name",
abbr: "Name",
// Allows user clicks on the header to sort the table rows by the
// values in this column. Requires the `datatable-sort` module.
sortable: true
},
{
key: "mfr-parts-database-price",
label: "Wholesale Price",
abbr: "Price",
// The emptyCellValue provides default content if a data row has no
// value for this field
emptyCellValue: '<em>(not set)</em>',
// The allowHTML configuration permits markup in data values to pass
// directly into the cell's innerHTML.
allowHTML: true,
sortable: true
}
];
var data = ...
var table = new Y.DataTable({
columns: cols,
data : data
});
table.render('#example2');
```
<p>This code produces this table:</p>
<div id="example2" class="yui3-skin-sam"></div>
<script>
YUI().use('datatable-sort', function (Y) {
var cols = [
{
key: "mfr-parts-database-id",
label: "Mfr Part ID",
abbr: "ID"
},
{
key: "mfr-parts-database-name",
label: "Mfr Part Name",
abbr: "Name",
sortable: true
},
{
key: "mfr-parts-database-price",
label: "Wholesale Price",
abbr: "Price",
emptyCellValue: '<em>(not set)</em>',
allowHTML: true,
sortable: true
}
];
var data = [
{ "mfr-parts-database-id": "ga-3475", "mfr-parts-database-name": "gadget", "mfr-parts-database-price": "$6.99", cost: "$5.99" },
{ "mfr-parts-database-id": "sp-9980", "mfr-parts-database-name": "sprocket", "mfr-parts-database-price": "$3.75", cost: "$3.25" },
{ "mfr-parts-database-id": "wi-0650", "mfr-parts-database-name": "widget", "mfr-parts-database-price": "", cost: "$3.75" },
{ "mfr-parts-database-id": "nu-0001", "mfr-parts-database-name": "nut", "mfr-parts-database-price": "$0.25", cost: "$3.75" }
];
var table = new Y.DataTable({
columns: cols,
data: data
});
table.render("#example2");
});
</script>
<h4 id="nested">Multi-row Headers</h4>
<p>
Use the `children` column configuration to created nested column headers.
Parent columns are for display purposes only, not associated with any data,
and <em>should not have a `key` attribute</em> of their own.
</p>
<p>
The `children` configuration takes an array of column configurations, just
like the `columns` attribute itself.
</p>
```
var nestedCols = [
{
// Important: Parent columns do NOT get a key
// All Parent columns should have a label for the header content
label: "Train Schedule",
// Pass an array of column configurations (strings or objects) as children
children: [
"track",
{
label: "Route",
children: [
{ key: "from" },
{ key: "to" }
]
}
]
}
];
var data = [
{ track: "1", from: "Paris", to: "Amsterdam" },
{ track: "2", from: "Paris", to: "London" },
{ track: "3", from: "Paris", to: "Zurich" }
];
var table = new Y.DataTable.Base({
columns: nestedCols,
data : data,
caption: "Table with nested column headers"
}).render("#example3");
```
<p>This code produces this table:</p>
<div id="example3" class="yui3-skin-sam"></div>
<script>
YUI().use('datatable-base', function (Y) {
var nestedCols = [
{
label: "Train Schedule",
children: [
"track",
{
label: "Route",
children: [ { key: "from" }, { key: "to" } ]
}
]
}
];
var data = [
{ track: "1", from: "Paris", to: "Amsterdam" },
{ track: "2", from: "Paris", to: "London" },
{ track: "3", from: "Paris", to: "Zurich" }
];
var table = new Y.DataTable.Base({
columns: nestedCols,
data : data,
caption: "Table with nested column headers"
}).render("#example3");
});
</script>
<h3 id="data">Working with row data</h3>
<p>
Pass an array of data to the `data` attribute and DataTable will create a
`ModelList` and populate it with instances of a `Model` subclass tailor
made for your data. If you want to work with a specific Model class, pass
that class to the DataTable's `recordType` attribute at instantiation. If
you want to work with a specific ModelList instance, pass the instance to
the `data` attribute.
</p>
<p>
The important thing to remember about your Model data is that <strong>it
should be stored as pure data</strong>, not values formatted for display.
For example, the `datatable-sort` module adds the ability to sort your
table, but to do so, it needs to sort your data. If you are storing
numbers as strings, "10" will sort ahead of "2".
</p>
<p>
DataTable has a variety of <a href="#formatter">ways to format your data
for display</a>. But keep your Model data as free from UI concerns as
possible.
</p>
<h4 id="formatter">Formatting Cell Data</h4>
<p>DataTable provides three primary ways to format cell data, all defined in the column configuration:</p>
```
var cols = [
{ label: 'formatter', children: [
// 1. formatter strings
// mix the field value into the {value} placeholder
{
key: 'price',
label: 'string',
formatter: '${value}'
},
// 2. formatter functions
// can provide alternate content, add cell classes, refer to other data
// fields, etc (more below)
{
key: 'price',
label: 'function',
formatter: function (o) {
if (o.value > 100) {
o.className += ' yellow-background';
return '$' + (o.value * 0.75).toFixed(2);
}
}
},
// 3. nodeFormatter functions
// have access to the cell Node in the DOM, up to the <tbody> Node.
// Caveats apply; see below.
{
key: 'price',
label: 'nodeFormatter',
nodeFormatter: functions (o) {
if (o.value > 200) {
// Add a class to the <tr>
o.cell.ancestor().addClass('red-text');
o.value *= 0.75;
}
o.cell.setContent('$' + o.value.toFixed(2));
}
}
},
...
];
```
INSERT CAVEAT ABOUT allowHTML vs formatters
<table>
<thead>
<tr>
<th>Property</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>`tbody`</td>
<td>The `&lt;tbody&gt;` node containing the cell.</td>
</tr>
<tr>
<td>`tr`</td>
<td>The `&lt;tr&gt;` node containing the cell.</td>
</tr>
<tr>
<td>`td`</td>
<td>The cell `&lt;td&gt;` node. As of 3.4.1, this property
is <strong>not provided by default</strong>, but can be generated by the
<a href="{{apiDocs}}/classes/DataTable.html#methods_createCell">createCell</a>
method.</td>
</tr>
<tr>
<td>`value`</td>
<td>Usually the value stored in the `Record` for the column. This is the default content that will be displayed.</td>
</tr>
<tr>
<td>`record`</td>
<td>The `Record` instance containing the data for all cells in the row.</td>
</tr>
<tr>
<td>`data`</td>
<td>The raw data collection from the `Record` instance.</td>
</tr>
<tr>
<td>`rowindex`</td>
<td>The row number of the `&lt;tr&gt;` node containing the cell (zero based).</td>
</tr>
<tr>
<td>`column`</td>
<td>The `Column` instance for the cell's column.</td>
</tr>
<tr>
<td>`classnames`</td>
<td>The classname corresponding to the ID of the cell's column.</td>
</tr>
<tr>
<td>`headers`</td>
<td>The Array of IDs from all `&lt;th&gt;`s corresponding to the cell (mostly relevant to nested headers).</td>
</tr>
</tbody>
</table>
```
// The custom formatter function recieves an object
var calculate = function (o) {
var cost = o.record.getValue("cost"),
price = o.record.getValue("price");
return "$" + (price - cost).toFixed(2);
};
// Assign the custom formatter in the column definition
var cols = [ "id", "name", { key: "profit", formatter: calculate } ];
var data = [
{ id: "ga-3475", name: "gadget", price: 6.99, cost: 4.99 },
{ id: "sp-9980", name: "sprocket", price: 3.75, cost: 2.75 },
{ id: "wi-0650", name: "widget", price: 4.25, cost: 3.25 }
];
var table = new Y.DataTable.Base({
columns: cols,
data: data,
caption: "Data formatting with custom function"
}).render("#function");
```
<p>
Integrate with the <a href="../datasource/">DataSource</a> data abstraction
utility to easily load data from remote sources and implement features such
as caching and polling.
</p>
```
var cols = [
"Title",
"Phone",
{ key: "Rating.AverageRating", label: "Rating" }
];
var myDataSource = new Y.DataSource.Get({
source: "http://query.yahooapis.com/v1/public/yql?&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
});
myDataSource.plug(Y.Plugin.DataSourceJSONSchema, {
schema: {
resultListLocator: "query.results.Result",
resultFields: [ "Title", "Phone", "Rating.AverageRating" ]
}
}),
var table = new Y.DataTable.Base({
columns: cols,
summary: "Pizza places near 98089"
});
table.plug(Y.Plugin.DataTableDataSource, {
datasource: myDataSource
})
table.render("#pizza");
// Load the data into the table
table.datasource.load({
request: "&q=select%20*%20from%20local.search%20where%20zip%3D%2794089%27%20and%20query%3D%27pizza%27"
});
// Make another request later
table.datasource.load({
request: "&q=select%20*%20from%20local.search%20where%20zip%3D%2794089%27%20and%20query%3D%27chinese%27"
});
```
<p>
Enable DataSource caching.
</p>
```
var cols = [
"Title",
"Phone",
{ key: "Rating.AverageRating", label: "Rating" }
];
var myDataSource = new Y.DataSource.Get({
source: "http://query.yahooapis.com/v1/public/yql?format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
});
myDataSource
.plug(Y.Plugin.DataSourceJSONSchema, {
schema: {
resultListLocator: "query.results.Result",
resultFields: ["Title", "Phone", "Rating.AverageRating"]
}
})
.plug(Y.Plugin.DataSourceCache, {
max: 3
});
var table = new Y.DataTable.Base({
columns: cols,
summary: "Pizza places near 98089",
caption: "Table with JSON data from YQL"
});
table
.plug(Y.Plugin.DataTableDataSource, {
datasource: myDataSource
})
.render("#pizza");
table.datasource.load({
request: "&q=select%20*%20from%20local.search%20where%20zip%3D%2794089%27%20and%20query%3D%27chinese%27"
});
```
<p>
Enable DataSource polling.
</p>
```
var cols = ["Title", "Phone", "Rating"];
var myDataSource = new Y.DataSource.IO({
source: "/path/to/service.php?"
});
myDataSource.plug(Y.Plugin.DataSourceXMLSchema, {
schema: {
resultListLocator: "Result",
resultFields: [
{ key: "Title", locator: "*[local-name() ='Title']" },
{ key: "Phone", locator: "*[local-name() ='Phone']" },
{ key: "Rating", locator: "*[local-name()='Rating']/*[local-name()='AverageRating']" }
]
}
});
var table = new Y.DataTable.Base({
columns: cols,
summary: "Chinese restaurants near 98089",
caption: "Table with XML data from same-domain script"
});
table
.plug(Y.Plugin.DataTableDataSource, {
datasource: myDataSource,
initialRequest: "zip=94089&query=chinese"
})
.render("#chinese");
myDataSource.setInterval(5000, {
request: "zip=94089&query=chinese",
callback: {
success: Y.bind(table.datasource.onDataReturnInitializeTable, table.datasource),
failure: Y.bind(table.datasource.onDataReturnInitializeTable, table.datasource)
}
});
```
<h3 id="sorting">Column sorting</h3>
<p>
Column sorting functionality can be added with the DataTableSort plugin
(provided by the `datatable-sort` module, or in the
`datatable` rollup module). Indicate which columns are sortable
by setting `sortable: true` in your column definitions.
</p>
```
var cols = [
{ key: "Company", sortable: true },
{ key: "Phone" },
{ key: "Contact", sortable: true }
];
var data = [
{ Company: "Company Bee", Phone: "415-555-1234", Contact: "Sally Spencer"},
{ Company: "Acme Company", Phone: "650-555-4444", Contact: "John Jones"},
{ Company: "Indutrial Industries", Phone: "408-555-5678", Contact: "Robin Smith"}
];
var table = new Y.DataTable.Base({
columns: cols,
data: data,
summary: "Contacts list",
caption: "Table with simple column sorting",
plugins: [ Y.Plugin.DataTableSort ]
}).render("#sort");
```
<h3 id="scrolling">Scrolling</h3>
<p>
<strong>Note:</strong> Scrolling is not currently supported on the Android
WebKit browser.
</p>
<p>
Scrolling functionality can be added with the DataTableScroll plugin
(provided by the `datatable-scroll` module or in the
`datatable` rollup module). Horizontal scrolling is enabled by
setting a `width` attribute value; fixed header vertical
scrolling is enabled by setting a `height` attribute value; and
xy-scrolling is enabled by setting both `width` and
`height` values.
</p>
```
var cols = [
{ key: "Company" },
{ key: "Phone" },
{ key: "Contact" }
];
var data = [
{ Company: "Company Bee", Phone: "415-555-1234", Contact: "Sally Spencer"},
{ Company: "Acme Company", Phone: "650-555-4444", Contact: "John Jones"},
{ Company: "Indutrial Industries", Phone: "408-555-5678", Contact: "Robin Smith"}
];
var table = new Y.DataTable.Base({
columns: cols,
data: data,
});
table
.plug(Y.Plugin.DataTableScroll, {
width: "300px",
height: "200px"
})
.render("#scroll");
```
<h2 id="knownissues">Known Issues</h2>
<ul>
<li>
Scrolling is
<a href="http://yuilibrary.com/projects/yui3/ticket/2529761">not
currently supported on Android</a> WebKit browser.
</li>
<li>Scrolling DataTable does
<a href="http://yuilibrary.com/projects/yui3/ticket/2531047">not appear
scrollable</a> in iOS and OS X 10.7 in Safari 5.1+ and Chrome 15+.
</li>
</ul>