5
<title>DataTable</title>
6
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Maven+Pro:400,700">
7
<link rel="stylesheet" href="../../build/cssgrids/grids-min.css">
8
<link rel="stylesheet" href="../assets/css/main.css">
9
<link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
10
<script src="../../build/yui/yui-min.js"></script>
18
<a href="#toc" class="jump">Jump to Table of Contents</a>
22
<div class="yui3-u-3-4">
24
<div class="content"><style type="text/css">
28
border: 1px solid #d0d5ec;
31
.yui3-datatable table {
35
.yui3-datatable td, .yui3-datatable th {
39
.yui3-datatable-col-Module {
43
.yui3-skin-sam .yui3-datatable-message-content {
45
border-bottom: 0 none;
50
border: 1px solid #eac9a9;
51
-moz-border-radius: 3px;
52
-webkit-border-radius: 3px;
55
-moz-box-shadow: 0 0 5px #ccc8b3;
56
-webkit-box-shadow: 0 0 5px #ccc8b3;
57
box-shadow: 0 0 5px #ccc8b3;
65
<div class="intro component">
67
The DataTable widget is responsible for rendering columnar data into a
68
highly customizable and fully accessible HTML table. The core
69
functionality of DataTable is to visualize structured data as a table.
70
A variety of class extensions can then be used to add features to the
71
table such as sorting and scrolling.
75
<h2 id="getting-started">Getting Started</h2>
78
To include the source files for DataTable and its dependencies, first load
79
the YUI seed file if you haven't already loaded it.
82
<pre class="code prettyprint"><script src="http://yui.yahooapis.com/3.5.0/build/yui/yui-min.js"></script></pre>
86
Next, create a new YUI instance for your application and populate it with the
87
modules you need by specifying them as arguments to the <code>YUI().use()</code> method.
88
YUI will automatically load any dependencies required by the modules you
92
<pre class="code prettyprint"><script>
93
// Create a new YUI instance and populate it with the required modules.
94
YUI().use('datatable', function (Y) {
95
// DataTable is available and ready for use. Add implementation
96
// code here.
98
</script></pre>
102
For more information on creating YUI instances and on the
103
<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_use"><code>use()</code> method</a>, see the
104
documentation for the <a href="../yui/index.html">YUI Global Object</a>.
109
<h2 id="migration-intro">Upgrading from version 3.4.1 or older?</h2>
112
DataTable was refactored for 3.5.0. Some APIs were changed in backward
117
Read the <a href="migration.html">3.5.0 Migration Guide</a> for tips to
118
avoid unpleasant surprises. If you still run into issues, please
119
<a href="../../../projects/yui3/newticket/">file a ticket</a>.
123
If you are unable to upgrade due to unresolvable issues, you can use the
124
<a href="../datatable-deprecated/index.html"><code>datatable-deprecated</code></a>
125
module suite, which is equivalent to the 3.4.1 implementation. But be
126
aware that these modules will be removed in a future version of YUI.
130
<h2 id="using">DataTable Basics</h2>
133
A basic DataTable is made of columns and rows. Define the columns you
134
want to display in your DataTable with the <code>columns</code> attribute. Rows are
135
created for you based on the data you provide to the <code>data</code> attribute.
139
Under the hood, the DataTable class uses a
140
<a href="../model-list/index.html">ModelList</a> instance to manage the row
141
data properties. Read the <a href="#data">Table Data Configuration</a>
142
section below for details about how to load, configure, and work with the
146
<pre class="code prettyprint">// Columns must match data object property names
148
{ id: "ga-3475", name: "gadget", price: "$6.99", cost: "$5.99" },
149
{ id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
150
{ id: "wi-0650", name: "widget", price: "$4.25", cost: "$3.75" }
153
var table = new Y.DataTable({
154
columns: ["id", "name", "price"],
157
// Optionally configure your table with a caption
158
caption: "My first DataTable!",
160
// and/or a summary (table attribute)
161
summary: "Example DataTable showing basic instantiation configuration"
164
table.render("#example");</pre>
167
<p>This code produces this table:</p>
169
<div id="basic-example" class="yui3-skin-sam"></div>
172
YUI({ filter: 'raw' }).use('datatable-base', function (Y) {
173
// Columns must match data object property names
175
{ id: "ga-3475", name: "gadget", price: "$6.99", cost: "$5.99" },
176
{ id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
177
{ id: "wi-0650", name: "widget", price: "$4.25", cost: "$3.75" }
180
var table = new Y.DataTable({
181
columns: ["id", "name", "price"],
183
caption: "My first DataTable!",
184
summary: "Example DataTable showing basic instantiation configuration"
187
table.render("#basic-example");
191
<h2 id="columns">Column Configuration</h2>
194
The <code>columns</code> attribute takes an array of field names that correspond to
195
property names in the <code>data</code> objects. These field names are called "keys".
196
As long as these keys exist in your data, DataTable will display the
197
values in the table. By default, the key is also used as the label of the
203
Use objects instead of key strings to customize how the cells in a column
207
<pre class="code prettyprint">// Columns must match data object property names
209
{ id: "ga-3475", name: "gadget", price: "$6.99", cost: "$5.99" },
210
{ id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
211
{ id: "wi-0650", name: "widget", /* missing */ cost: "$3.75" }
214
var table = new Y.DataTable({
217
{ key: "name", label: "part name" },
218
{ key: "price", allowHTML: true, emptyCellValue: "<em>(not set)</em>" },
224
table.render("#example");</pre>
227
<p>This code produces this table:</p>
229
<div id="column-example1" class="yui3-skin-sam"></div>
232
YUI().use('datatable-base', function (Y) {
233
// Columns must match data object property names
235
{ id: "ga-3475", name: "gadget", price: "$6.99", cost: "$5.99" },
236
{ id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
237
{ id: "wi-0650", name: "widget", cost: "$3.75" }
240
var table = new Y.DataTable({
243
{ key: "name", label: "part name" },
244
{ key: "price", allowHTML: true, emptyCellValue: "<em>(not set)</em>" },
250
table.render("#column-example1");
255
Some column configurations affect the table headers and others affect the
260
Use the <code>key</code> property to reference the associated data field when
261
configuring columns with objects. Other supported configuration
262
properties are listed in <a href="#column-config">Appendix A</a> below.
266
<h3 id="nested">Stacked Column Headers</h3>
269
Use the <code>children</code> column configuration to create multiple rows of column
273
<pre class="code prettyprint">var columns = [
274
'username',
276
// Important: Parent columns do NOT get a key...
278
// but DO get a label
279
label: "Access",
281
// Pass an array of column configurations (strings or objects) as children
290
{ username: "root", read: true, write: true },
291
{ username: "spilgrim", read: true, write: false },
292
{ username: "fizzgig", read: false, write: false }
295
var table = new Y.DataTable({
298
}).render("#example");</pre>
301
<p>This code produces this table:</p>
303
<div id="nested-example" class="yui3-skin-sam"></div>
306
YUI().use('datatable-base', function (Y) {
308
{ username: "root", read: true, write: true },
309
{ username: "spilgrim", read: true, write: false },
310
{ username: "fizzgig", read: false, write: false }
313
var table = new Y.DataTable({
317
// Important: Parent columns do NOT get a key...
319
// but DO get a label
322
// Pass an array of column configurations (strings or objects) as children
330
}).render("#nested-example");
335
<code>children</code> takes an array of column configurations, just like the <code>columns</code>
336
attribute itself. The columns defined in the <code>children</code> property will have
337
header cells rendered below the parent column's header.
341
Columns that have <code>children</code> don't relate directly to the data cells in the
342
table rows, so they <strong>should not</strong> have a <code>key</code> configured.
343
They should, however, include a <code>label</code> to provide the header's content.
346
<h3 id="formatters">Formatting Cell Data</h3>
349
To customize the display of cell data in a column, DataTable provides the
350
<code>formatter</code> and <code>nodeFormatter</code> column configurations. Both configurations
351
accept functions, but <code>formatter</code> will also accept a template string.
355
<code>formatter</code>s are expected to return the string content to populate each
356
cell in that column, and <code>nodeFormatter</code>s are provided with the cell Nodes
357
and expected to populate them using the Node API.
361
For best performance, <strong><a href="#formatter-vs-nodeformatter">avoid
362
<code>nodeFormatter</code>s unless absolutely necessary</a></strong>.
365
<pre class="code prettyprint">var columns = [
368
key: 'cost',
369
formatter: '${value}' // formatter template string
372
key: 'price',
373
formatter: function (o) {
374
if (o.value > 3) {
375
o.className += ' yellow-background';
378
return '$' + o.value.toFixed(2);
382
label: 'profit',
383
nodeFormatter: function (o) {
384
var profit = o.data.price - o.data.cost,
385
prefix = '$',
389
prefix = '-' + prefix;
390
profit = Math.abs(profit);
391
row = o.cell.ancestor();
393
o.cell.addClass('negative');
395
// Assign a rowspan to the first cell and add a new row
396
// below this one to span the last three columns
397
row.one('td').setAttribute('rowspan', 2);
400
'<tr class="auth"><td colspan="3">' +
401
'<button class="ok">authorize</button>' +
402
'<button class="stop">discontinue</button>' +
403
'</td></tr>',
407
o.cell.set('text', prefix + profit.toFixed(2));
413
<p>This code produces this table:</p>
415
<div id="formatter-example" class="yui3-skin-sam">
417
.yui3-datatable .yui3-datatable-data .expensive {
418
background-color: #ffe;
420
.yui3-skin-sam .yui3-datatable-data .auth td {
421
border-bottom: 1px dashed #cbcbcb;
429
background-color: #fff;
430
border-top: 1px dashed #cbcbcb;
431
border-left: 1px solid #cbcbcb;
438
YUI().use('datatable-base', function (Y) {
443
formatter: '${value}' // formatter template string
447
formatter: function (o) {
449
o.className += ' expensive';
452
return '$' + o.value.toFixed(2);
457
nodeFormatter: function (o) {
458
var profit = o.data.price - o.data.cost,
463
prefix = '-' + prefix;
464
profit = Math.abs(profit);
465
row = o.cell.ancestor();
467
o.cell.addClass('negative');
469
row.one('td').setAttribute('rowspan', 2);
472
'<tr class="auth"><td colspan="3">' +
473
'<button class="ok">authorize</button>' +
474
'<button class="stop">discontinue</button>' +
479
o.cell.setContent(prefix + profit.toFixed(2));
485
{ item: "widget", cost: 23.57, price: 47.5 },
486
{ item: "gadget", cost: 0.11, price: 6.99 },
487
{ item: "sprocket", cost: 4.08, price: 3.75 },
488
{ item: "nut", cost: 0.01, price: 0.25 }
491
var table = new Y.DataTable({
494
}).render("#formatter-example");
499
The parameters passed to <code>formatter</code> functions and <code>nodeFormatter</code>
500
functions are described in <a href="#formatter-props">Appendix B</a> and <a
501
href="#nodeformatter-props">Appendix C</a>, respectively.
505
<strong>Note</strong>: It's highly recommended to keep the data in the
506
underlying <code>data</code> ModelList as pure data, free from presentational
507
concerns. For example, use real numbers, not numeric strings, and store
508
link urls and labels either in separate data fields or in a single data
509
field, but as separate properties of a value object. This allows the data
510
to be used for calculations such as sorting or averaging.
513
<h4 id="formatter-function">Setting content with <code>formatter</code> functions</h4>
516
Set the cell content with column <code>formatter</code>s by returning the desired
517
content string from the function. Alternately, just update <code>o.value</code> with
518
the new value in the object passed as an argument to the <code>formatter</code>. When
519
updating <code>o.value</code> <em>do not include a return statement</em>.
523
<code>formatters</code> are very powerful because not only do they have access to the
524
record's value for that column's field, but they also receive the rest of
525
the record's data, the record Model instance itself, and the column
526
configuration object. This allows you to include any extra configurations
527
in your column configuration that might be useful to customizing how cells
528
in the column are rendered.
531
<pre class="code prettyprint">function currency(o) {
532
return Y.DataType.number.format(o.value, {
533
prefix : o.column.currencySymbol || '$',
534
decimalPlaces : o.column.decimalPlaces || 2,
535
decimalSeparator : o.column.decimalSeparator || '.',
536
thousandsSeparator: o.column.thousandsSeparator || ','
541
{ key: "price", formatter: currency, decimalPlaces: 3 },
546
See <a href="#formatter-props">Appendix B</a> for a list of all properties
547
passed to <code>formatter</code> functions.
550
<h4 id="nodeformatters">Setting content with <code>nodeFormatter</code> functions</h4>
553
Unlike <code>formatters</code> which can effectively default to the normal rendering
554
logic by leaving <code>o.value</code> unchanged, <code>nodeFormatters</code> must assign content
555
to the cells themselves. The cell's initial classes will be set up, but
556
that's it. Everything else is your responsibility.
560
<strong><code>nodeFormatter</code>s should return <code>false</code></strong>.
561
<a href="formatter-vs-nodeformatter">See below</a> for details.
565
While there are <a href="#formatter-vs-nodeformatter">few scenarios that
566
require <code>nodeFormatter</code>s</a>, they do have the benefits of having the Node
567
API for constructing more complex DOM subtrees and the ability to access
568
all nodes in the <code><tbody></code>. This means they can reference, and even modify,
573
Like <code>formatters</code>, <code>nodeFormatters</code> are provided with the data field value,
574
the record data, the record Model instance, and the column configuration
579
See <a href="#nodeformatter-props">Appendix C</a> for a list of all
580
properties passed to <code>nodeFormatter</code> functions.
583
<h4 id="formatter-vs-nodeformatter">Why <code>formatter</code> and <code>nodeFormatter</code>?</h4>
586
For good rendering performance and memory management, DataTable creates
587
table content by assembling <code>innerHTML</code> strings from templates, with
588
<code>{placeholder}</code> tokens replaced with your data. However, this means that
589
the Nodes don't exist yet when a column's <code>formatter</code>s are applied.
593
To minimize the need to create Nodes for each cell, the default rendering
594
logic supports the addition of cell classes as well as row classes via
595
<code>formatter</code> functions. Event subscriptions should be
596
<a href="http://yuilibrary.com/yui/docs/event/delegation.html">delegated</a>
597
from the DataTable instance itself using the
598
<a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html#method_delegate"><code>delegate()</code> method</a>.
602
On the rare occasion that you <em>must</em> use Nodes to supply the cell
603
data, DataTable allows a second pass over the generated DOM elements once
604
the initial string concatenation has been completed and the full HTML
609
It is important to note that <code>nodeFormatters</code> will necessarily create a
610
Node instance for each cell in that column, which will increase the memory
611
footprint of your application. If the Node instance wrappers around the
612
DOM elements don't need to be maintained beyond the life of the
613
<code>nodeFormatter</code>, return <code>false</code> to remove them from the internal object
614
cache. <strong>This will not remove the rendered DOM, but it will remove
615
event subscriptions made on those Nodes</strong>.
619
In general, <code>nodeFormatter</code>s should only be used if absolutely necessary,
620
and should <em>always return <code>false</code></em>.
623
<h4 id="formatters-vs-empty">Formatters vs. <code>emptyCellValue</code></h4>
626
The <code>emptyCellValue</code> configuration is useful to provide fallback content in
627
the case of missing or empty column data, but it interacts with each type of
628
formatter differently.
632
String formatters will only be applied if the field data for that cell is
633
not <code>undefined</code>. This allows the <code>emptyCellValue</code> to populate the cell.
637
Function formatters are applied before the return value or (potentially
638
altered) <code>o.value</code> property is tested for <code>undefined</code>, <code>null</code>, or the empty
639
string. In any of these cases, the <code>emptyCellValue</code> populates the cell.
643
The <code>emptyCellValue</code> configuration is ignored by columns configured with
644
<code>nodeFormatter</code>s.
648
<h2 id="data">Table Data Configuration</h2>
651
Each record in the table is stored as a
652
<a href="../model/index.html">Model</a> instance, where the
653
keys of the record objects become Model attributes. This allows you to
654
interact with the models as you would any other <a
655
href="../base/index.html">Base</a>-based class, with <code>get(attr)</code>,
656
<code>set(attr, value)</code>, and subscribing to attribute change events.
659
<pre class="code prettyprint">var data = [
660
{ item: "widget", cost: 23.57, price: 47.5 },
661
{ item: "gadget", cost: 0.11, price: 6.99 },
662
{ item: "sprocket", cost: 4.08, price: 3.75 },
663
{ item: "nut", cost: 0.01, price: 0.25 }
666
var table = new Y.DataTable({
667
columns: ["item", "cost", "price"],
671
var sprocket = table.getRecord(2);
673
// Fires a costChange event, and the table is updated if rendered
674
sprocket.set('cost', 2.65);</pre>
678
The Model class used to store the record data is created for you, based on
679
the objects in the <code>data</code> array. If <code>data</code> is not set, the column keys
680
identified in the <code>columns</code> configuration is used.
683
<h3 id="recordtype">Specifying the Record Model</h3>
686
To use a custom Model for your records, pass your Model subclass to the
687
<code>recordType</code> attribute.
690
<pre class="code prettyprint">var pieTable = new Y.DataTable({
691
recordType: Y.PieModel,
692
columns: ['slices', 'type'],
694
// Y.PieModel has attributes 'slices', which defaults to 6, and 'type',
695
// which defaults to 'apple'. Records can use these defaults.
696
{ type: 'lemon meringue' },
697
{ type: 'chocolate creme', slices: 8 },
698
{} // equivalent to { type: 'apple', slices: 6 }
702
// Y.PieModel has its idAttribute assigned to 'type', overriding the default
703
// of 'id'. Fetch a PieModel by its id.
704
var applePie = pieTable.getRecord('apple');
706
// eatSlice is a method on the Y.PieModel prototype
707
applePie.eatSlice();</pre>
711
Alternately, <code>recordType</code> will accept an array of attribute strings or an
712
<code>ATTRS</code> configuration object to make it easier to create custom attribute
713
behaviors without needing to explicitly build the Model subclass.
717
If the <code>columns</code> configuration is omitted, but the <code>recordType</code> is set, the
718
<code>columns</code> will default to the <code>recordType</code>'s attributes.
721
<pre class="code prettyprint">var data = [
722
{ item: "widget", cost: 23.57, price: 47.5 },
723
{ item: "gadget", cost: 0.11, price: 6.99 },
724
{ item: "sprocket", cost: 4.08, price: 3.75 },
725
{ item: "nut", cost: 0.01, price: 0.25 }
728
// Effectively synonymous with setting the columns attribute if no special
729
// column configuration is needed.
730
var table = new Y.DataTable({
731
recordType: [ 'item', 'cost', 'price' ],
735
// Or for more control, pass an ATTRS configuration object
736
var table = new Y.DataTable({
741
setter: function (val) { return +val || 0; }
744
valueFn: function () { return (this.get('cost') + 0.1) * 10; },
745
setter: function (val) { return +val || 0; }
753
When the table data is loaded asychronously, it is often a good idea to
754
configure the <code>recordType</code>. This can prevent the generation of a record
755
Model that is missing fields that are omitted from the <code>columns</code>
756
configuration because they aren't intended for viewing.
759
<h3 id="modellist">The <code>data</code> ModelList</h3>
762
The record Models are stored in a
763
<a href="../model-list/index.html">ModelList</a>, which is assigned to the
764
<code>data</code> <em>property</em> on the instance (for easier access than going through <code>table.get('data')</code>).
767
<pre class="code prettyprint">var records = [
768
{ item: "widget", cost: 23.57, price: 47.5 },
769
{ item: "gadget", cost: 0.11, price: 6.99 },
770
{ item: "sprocket", cost: 4.08, price: 3.75 }
773
var table = new Y.DataTable({
774
columns: ["item", "cost", "price"],
778
// Add a new Model using the ModelList API. This will fire
779
// events and change the table if rendered.
780
table.data.add({ item: "nut", cost: 0.01, price: 0.25 });</pre>
784
When assigning the DataTable's <code>data</code> attribute with an array, a ModelList
785
is created for you. But you can also pass a ModelList instance if you are
786
sharing a ModelList between widgets on the page, or you have created custom
787
Model and ModelList classes with additional logic, such as adding a
788
<a href="../model-list/#implementing-a-list-sync-layer">data sync layer</a>.
791
<pre class="code prettyprint">var table = new Y.DataTable({
792
columns: ['type', 'slices'],
793
data: new Y.PieList()
796
// The Y.PieList class implements a sync layer, enabling its load() method
797
table.data.load(function () {
798
table.render('#pies');
802
<h3 id="getting-data">Getting Remote Table Data</h3>
805
To fetch remote data, you have three options:
811
<strong>For quick one-offs</strong>, you can load and parse the
812
data manually, using <code>Y.io(...)</code>, <code>Y.jsonp(...)</code>, etc., then assign
813
that data to the DataTable's <code>data</code> attribute. This isn't very
814
elegant or maintainable, so is best avoided for anything other than
820
<strong>For the most control</strong>, better maintainability, and
821
better encapsulation of business logic, create Model and ModelList
823
<a href="../model-list/#implementing-a-list-sync-layer">implement a
824
sync layer</a> as suggested above.
829
<strong>For common read-only scenarios</strong>, use the
830
<a href="http://yuilibrary.com/yui/docs/api/classes/Plugin.DataTableDataSource.html"><code>Y.Plugin.DataTableDataSource</code></a>
831
plugin to bind your table to a
832
<a href="../datasource/index.html"><code>DataSource</code></a> instance. Use
833
plugins to add DataSource features.
839
<pre class="code prettyprint">// Create a JSONP DataSource to query YQL
840
var myDataSource = new Y.DataSource.Get({
841
source: 'http://query.yahooapis.com/v1/public/yql?format=json&' +
842
'env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&q='
845
myDataSource.plug(Y.Plugin.DataSourceJSONSchema, {
847
resultListLocator: 'query.results.Result',
852
// Important that record fields NOT include ".", so
853
// extract nested data with locators
854
key: 'Rating',
855
locator: "Rating.AverageRating"
860
.plug(Y.Plugin.DataSourceCache, {
864
// No data is provided at construction because it will load via the
865
// DataTableDataSource plugin
866
var table = new Y.DataTable({
867
columns: ['Title', 'Phone', 'Rating'],
868
summary: 'Pizza places near 98089'
871
table.plug(Y.Plugin.DataTableDataSource, {
872
datasource: myDataSource
875
// Initially render an empty table and show a loading message
876
table.render('#pizza')
877
.showMessage('loadingMessage');
879
// Load the data into the table
880
table.datasource.load({
881
request: encodeURIComponent(
882
'select *' +
883
' from local.search' +
884
' where zip="94089"' +
885
' and query="pizza"');
889
<h2 id="features">DataTable Modules and Features</h2>
892
For a basic, stripped down <code>Y.DataTable</code> class, include the <code>datatable-base</code>
893
module in your <code>use()</code>.
897
Feature modules, such as <code>datatable-sort</code>, will bring in <code>datatable-base</code>
898
automatically. By including only feature modules in your <code>use()</code>, you will
899
get a <code>Y.DataTable</code> that supports specifically those features, without
900
extra code for other features you won't be using.
904
The <code>datatable</code> module is a bundle of <code>datatable-base</code> plus a set of common
905
feature modules. Other feature modules need to be included explicitly in
914
<th>In <code>datatable</code>?</th>
919
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-core.html"><code>datatable-core</code></a></td>
921
The core API for DataTable, implemented as a class extension, used
922
by <code>datatable-base</code> to create <code>Y.DataTable</code> and <code>Y.DataTable.Base</code>.
927
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-base.html"><code>datatable-base</code></a></td>
929
Creates the <code>Y.DataTable</code> and <code>Y.DataTable.Base</code> classes, and
930
defaults the <code>headerView</code> and <code>bodyView</code> to <code>Y.DataTable.HeaderView</code>
931
and <code>Y.DataTable.BodyView</code> respectively.
936
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-head.html"><code>datatable-head</code></a></td>
938
Creates the <code>Y.DataTable.HeaderView</code> class as a subclass of
939
<code>Y.View</code>. DataTable defers rendering of the <code><thead></code> content to
940
this View when it is passed as the DataTable's <code>headerView</code>
941
attribute (the default, as set by <code>datatable-base</code>).
946
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-body.html"><code>datatable-body</code></a></td>
948
Creates the <code>Y.DataTable.BodyView</code> class as a subclass of
949
<code>Y.View</code>. DataTable defers rendering of the <code><tbody></code> content to
950
this View when it is passed as the DataTable's <code>bodyView</code>
951
attribute (the default, as set by <code>datatable-base</code>).
956
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-message.html"><code>datatable-message</code></a></td>
958
Creates the <code>Y.DataTable.Message</code> class extension and adds
959
<code>showMessage</code> and <code>hideMessage</code> methods to <code>Y.DataTable</code>.
964
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-column-widths.html"><code>datatable-column-widths</code></a></td>
966
Creates the <code>Y.DataTable.ColumnWidths</code> class extension, and adds
967
support for the <code>width</code> property in column configuration objects
968
to <code>Y.DataTable</code>.
973
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-mutable.html"><code>datatable-mutable</code></a></td>
975
Creates the <code>Y.DataTable.Mutable</code> class extension and adds methods
976
such as <code>addRow</code>, <code>removeRow</code>, and <code>moveColumn</code> to <code>Y.DataTable</code>.
981
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-sort.html"><code>datatable-sort</code></a></td>
983
Creates the <code>Y.DataTable.Sort</code> class extension and adds methods
984
<code>sort</code> and <code>toggleSort</code> as well as attributes <code>sortable</code> and
985
<code>sortBy</code> to <code>Y.DataTable</code>. Enables sorting the table rows by
986
clicking on column headers.
991
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-datasource.html"><code>datatable-datasource</code></a></td>
993
Creates the <code>Y.Plugin.DataTableDataSource</code> plugin for binding a
994
DataSource instance to the table as its source of record data.
999
<td><a href="http://yuilibrary.com/yui/docs/api/modules/datatable-scroll.html"><code>datatable-scroll</code></a></td>
1001
Creates the <code>Y.DataTable.Scroll</code> class extension and adds attribute
1002
<code>scrollable</code> to <code>Y.DataTable</code>. Adds support for vertically and/or
1003
horizontally scrolling table rows within fixed table dimensions.
1010
<h3 id="base">Features in <code>DataTable.Base</code></h3>
1013
By including only <code>datatable-base</code> in your <code>use()</code> line, you get both
1014
<code>Y.DataTable</code> and <code>Y.DataTable.Base</code> classes. With no other module
1015
inclusion, these classes are effectively the same. When additional
1016
DataTable related modules are included, those modules' features will
1017
usually be added to <code>Y.DataTable</code>, but <strong>never</strong> to
1018
<code>Y.DataTable.Base</code>.
1022
Though it can be instantiated, the purpose of <code>Y.DataTable.Base</code> is
1023
primarily as a superclass to a custom DataTable implementation that has a
1024
locked set of features that will not be modified, as <code>Y.DataTable</code> can be,
1025
by the inclusion of other modules.
1028
<pre class="code prettyprint">// Create a custom DataTable that includes only the core set of APIs, plus
1029
// sorting and message support.
1030
Y.MyDataTable = Y.Base.create('myTable', Y.DataTable.Base,
1031
[ Y.DataTable.Sort, Y.DataTable.Message ]);
1033
Y.use('datatable-scroll', function (Y) {
1034
// Y.DataTable now has support for scrolling
1035
var table = new Y.DataTable({ scrollable: 'y', ... });
1037
// Y.MyDataTable does not (the config does nothing)
1038
var myTable = new Y.MyDataTable({ scrollable: 'y', ... });
1043
<code>Y.DataTable.Base</code> includes the <code>columns</code>, <code>data</code>, <code>caption</code>, and other
1044
basic table attributes, the underlying ModelList and View rendering
1045
architecture, as well as methods to fetch rows and cells or columns and
1050
Rendering features include most column configurations, such as <code>children</code>
1051
and <code>allowHTML</code>, as well as column formatting options <code>formatter</code>,
1052
<code>nodeFormatter</code>, <code>cellTemplate</code>, etc.
1055
<h3 id="datatable-message">Table Messages</h3>
1058
The <code>datatable-message</code> module adds the ability to display a message in the
1059
table body. By default, the "emptyMessage" will display when the table's
1060
ModelList has no data records. The message will hide when data is added.
1063
<pre class="code prettyprint">var table = new Y.DataTable({
1064
columns: ["id", "name", "price"],
1066
}).render('#example');</pre>
1069
<p>This code produces this table:</p>
1071
<div id="message-example" class="yui3-skin-sam"></div>
1074
YUI({ filter: 'raw' }).use('datatable-message', function (Y) {
1075
var table = new Y.DataTable({
1076
columns: ["id", "name", "price"],
1078
}).render('#message-example');
1083
Use <code>table.showMessage("message")</code> and <code>table.hideMessage()</code> to toggle the
1088
<code>showMessage</code> supports internationalized strings by using a few named
1089
strings, which are registered in the language packs for the
1090
<code>datatable-message</code> module . These strings are currently:
1095
<code>table.showMessage("emptyMessage")</code> defaults to "No data to display".
1098
<code>table.showMessage("loadingMessage")</code> defaults to "Loading...".
1103
Other values passed to <code>showMessage</code> will pass that content directly
1104
through to the message Node.
1107
<h3 id="colwidths">Column Width Configuration</h3>
1110
The <code>datatable-column-widths</code> module adds basic support for specifying
1114
<pre class="code prettyprint">var table = new Y.DataTable({
1116
{ key: 'item', width: '125px' },
1117
{ key: 'cost', formatter: '${value}' },
1121
}).render("#example");</pre>
1124
<p>This code produces this table:</p>
1126
<div id="colwidths-example" class="yui3-skin-sam"></div>
1129
YUI({ filter: 'raw' }).use('datatable-column-widths', function (Y) {
1131
{ item: "widget", cost: 23.57, price: 47.5 },
1132
{ item: "gadget", cost: 0.11, price: 6.99 },
1133
{ item: "sprocket", cost: 4.08, price: 3.75 },
1134
{ item: "nut", cost: 0.01, price: 0.25 }
1137
var table = new Y.DataTable({
1139
{ key: 'item', width: '125px' },
1140
{ key: 'cost', formatter: '${value}' },
1141
{ key: 'price', formatter: '${value}' },
1142
{ key: 'profit', formatter: function (o) {
1143
var price = o.data.price,
1146
return (((price - cost) / cost) * 100).toFixed(2) + '%';
1151
}).render("#colwidths-example");
1156
<strong>CAVEAT</strong>: Column widths will expand beyond the configured
1157
value if column cells contain data that is long and can't line-wrap. Also,
1158
column widths may be reduced below the configured value if the table width
1159
(by configuring the DataTable's <code>width</code> attribute, or constrained by a
1160
narrow containing element) is too narrow to fit all data at the configured
1165
To force column widths, including cell data truncation and allowing the
1166
table to spill beyond its configured or inherited width, wrap the cell
1167
content in a <code><div></code> either by configuring the column's <code>formatter</code> or
1168
<code>cellTemplate</code>, then assign the <code><div></code>'s CSS style with the desired width
1169
(or "inherit"), plus <code>overflow: hidden;</code>. Then set the DataTable column's
1170
<code>width</code> configuration accordingly.
1173
<h3 id="sorting">Column sorting</h3>
1176
The <code>datatable-sort</code> module adds support for sorting the table rows either
1177
through the added APIs or by clicking on the table headers.
1181
By default, when <code>datatable-sort</code> is included, DataTables will inspects
1182
the <code>columns</code> objects, looking for <code>sortable: true</code> to enable table sorting
1183
by those columns, triggered by clicking on their respective headers.
1185
<pre class="code prettyprint">var cols = [
1186
{ key: "Company", sortable: true },
1187
{ key: "Phone" },
1188
{ key: "Contact", sortable: true }
1193
For convenience, you can enable header-click sorting for all columns by
1194
setting the <code>sortable</code> attribute to <code>true</code>, or pass an array of column keys
1195
to enable just those column's headers.
1198
<pre class="code prettyprint">// Set all columns to be sortable
1199
var table = new Y.DataTable({
1200
columns: ["Company", "Phone", "Contact"],
1203
}).render("#example");</pre>
1206
<p>This code produces this table:</p>
1208
<div id="sort-example1" class="yui3-skin-sam"></div>
1211
YUI({ filter: 'raw' }).use('datatable-sort', function (Y) {
1212
var table = new Y.DataTable({
1213
columns: ['Company', 'Phone', 'Contact'],
1215
{ Company: "Company Bee", Phone: "415-555-1234", Contact: "Sally Spencer"},
1216
{ Company: "Acme Company", Phone: "650-555-4444", Contact: "John Jones"},
1217
{ Company: "Indutrial Industries", Phone: "408-555-5678", Contact: "Robin Smith"}
1220
}).render('#sort-example1');
1225
Hold down the <code>shift</code> key while clicking on column headers to subsort by
1226
that column. Doing so repeatedly will toggle the subsort direction.
1230
As long as the <code>datatable-sort</code> module has been included, you will always
1231
be able to sort the table data through the API, even by columns that aren't
1232
configured to accept header-click sorting.
1236
When a table is sorted, any new records added to the DataTable's ModelList
1237
will be inserted at the proper sorted index, as will the created table
1242
Disable header-click sorting by setting <code>sortable</code> to <code>false</code>.
1245
<h4 id="customsort">Custom Sorting</h4>
1248
Assign a function to a column's <code>sortFn</code> to support customized sorting. The
1249
function will receive the two records being compared and a boolean flag
1250
indicating a descending sort was requested.
1253
<pre class="code prettyprint">var columns = [
1255
key: 'id',
1256
label: '&#9679;', // a big dot
1257
formatter: function (o) {
1258
return o.value ? '' : '&#9679;'; // only new records have a dot
1261
sortFn: function (a, b, desc) {
1262
var aid = a.get('id'),
1263
bid = b.get('id'),
1264
acid = a.get('clientId'),
1265
bcid = b.get('clientId'),
1266
order = // existing records are equivalent
1267
(aid && bid) ? 0 :
1268
// new records are grouped apart from existing records
1269
(aid && -1) || (bid && 1) ||
1270
// new records are sorted by insertion order
1271
(acid > bcid) ? 1 : -(acid < bcid);
1273
return desc ? -order : order;
1280
The function must return 1, 0, or -1. 1 specifies that the Model passed as
1281
the first parameter should sort below the Model passed as the second
1282
parameter. -1 for above, and 0 if they are equivalent for the purpose of
1287
<h4 id="sortapi">Sorting Methods</h4>
1290
To sort the table in the code, call <code>table.sort(NAME OR KEY)</code>. To
1291
toggle the sort direction, call <code>table.toggleSort(NAME OR KEY)</code>.
1294
<pre class="code prettyprint">// Sorts the table by values in the price field in ascending order
1295
table.sort('price');
1297
// Flips to descending
1298
table.toggleSort('price');</pre>
1302
To sort by multiple columns, pass an array of column keys to <code>sort</code> or
1303
<code>toggleSort</code>.
1307
Calling <code>toggleSort</code> with no arguments will reverse all current sort
1308
directions. Calling with specific column names or keys will toggle only
1312
<pre class="code prettyprint">// Sort first by author, subsort by title in ascending order
1313
table.sort(['author', 'title']);
1315
// Now descending by author then title
1316
// same as table.toggleSort(['author', 'title']);
1319
// Now ascending by author, descending by title
1320
table.toggleSort('author');</pre>
1324
To specify a sort direction, pass an object instead of a string to <code>sort</code>.
1325
The object should have the column name as the key, and sort direction as its
1329
<pre class="code prettyprint">// Explicitly sort by price in descending order
1330
table.sort({ price: 'desc' });
1332
// Each column gets its own object
1333
table.sort([{ author: 'desc' }, { title: 'desc' }]);</pre>
1337
Acceptable values for the sort direction are "asc", "desc", 1, and -1. 1 is
1338
equivalent to "asc", and -1 to "desc".
1341
<h4 id="sortby">The <code>sortBy</code> Attribute</h4>
1344
Every sort operation updates the <code>sortBy</code> attribute. You can also trigger
1345
a sort by setting this attribute directly. It accepts the same values as
1346
the <code>sort</code> method.
1349
<pre class="code prettyprint">// Sort by author in descending order, then by title in ascending order
1350
table.set('sortBy', [{ author: -1 }, 'title']);</pre>
1354
To specify an initial sort order for your table, assign this attribute
1355
during instantiation. This will sort the data as soon as it is added
1356
to the table's ModelList.
1359
<pre class="code prettyprint">// Pre-sort the data
1360
var table = new Y.DataTable({
1361
columns: ['item', 'cost', 'price'],
1363
sortBy: { price: -1 }
1367
<h4 id="sortevent">The <code>sort</code> Event</h4>
1370
Clicking on a column header, or calling the <code>sort</code> or <code>toggleSort</code> methods
1371
will fire a <code>sort</code> method containing an <code>e.sortBy</code> property that
1372
corresponds to the requested sort column and direction. The value will be
1373
in either string or object format, depending on how each method was used.
1377
Preventing the <code>sort</code> event will prevent the <code>sortBy</code> attribute from being
1378
updated. Updating the <code>sortBy</code> attribute directly will not fire the <code>sort</code>
1379
event, but will still sort the data and update the table.
1382
<h3 id="mutation">Table Mutation APIs (<code>addRow</code>, etc)</h3>
1385
The <code>datatable-mutable</code> module adds APIs for adding, removing, and
1386
modifying records and columns.
1389
<h4 id="column-mutation">Column Mutation Methods</h4>
1392
Use the methods <code>addColumn</code>, <code>removeColumn</code>, <code>modifyColumn</code>, and
1393
<code>moveColumn</code> to update the table's configured <code>columns</code>.
1396
<pre class="code prettyprint">// Insert a column for the profit field in the data records as the third column
1397
table.addColumn('profit', 2);
1399
// Actually, make that the fourth column
1400
table.moveColumn('profit', 3);
1402
// Actually, strike that. Don't show it after all
1403
table.removeColumn('profit');
1405
// Instead, add a formatter to the price column that includes the profit data
1406
table.modifyColumn('price', {
1407
formatter: function (o) {
1408
return o.value + ' (' + (o.data.profit / o.data.cost).toFixed(2) + '%)';
1414
Each column mutation method fires an identically named event. See
1415
<a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html">the API docs</a> for details.
1418
<h4 id="row-mutation">Row Mutation Methods</h4>
1421
Use the methods <code>addRow</code>, <code>addRows</code>, <code>removeRow</code>, and <code>modifyRow</code> to update
1422
the table's ModelList.
1425
<pre class="code prettyprint">table.addRow({ item: 'collet', cost: 0.42, price: 2.65 });
1428
{ item: 'nut', cost: 0.42, price: 2.65 },
1429
{ item: 'washer', cost: 0.01, price: 0.08 },
1430
{ item: 'bit', cost: 0.19, price: 0.97 }
1433
// Remove table records by their Model, id, clientId, or index
1436
// Modify a record by passing its id, clientId, or index, followed by an
1437
// object with new field values
1438
table.modifyRow('record_4', { cost: 0.74 });</pre>
1441
Everything that's done by these methods can be accomplished through the
1442
table's ModelList instance methods, but having methods on the table itself
1443
can make the code more readable.
1446
<pre class="code prettyprint">// Same as table.addRow(...);
1447
table.data.add({ item: 'collet', cost: 0.42, price: 2.65 });</pre>
1451
By default, changes made to the table are only local, they don't update the
1452
server or other data origin if the data was served remotely. However, if
1453
your table's ModelList is built with a sync layer, the mutation methods
1454
can also trigger the appropriate sync behavior by passing an additional
1455
argument to the methods, an object with the property <code>sync</code> set to <code>true</code>.
1458
<pre class="code prettyprint">// Tell the server we're down to one slice of apple pie!
1459
table.modifyRow('apple', { slices: 1 }, { sync: true });
1461
// Uh oh, make that 0. No more apple pie :(
1462
table.removeRow('apple', { sync: true });</pre>
1466
If all modifications are destined for the server/origin, you can set the
1467
<code>autoSync</code> attribute to <code>true</code>, and the row mutation methods will
1468
automatically call into the sync layer.
1471
<pre class="code prettyprint">var pies = new Y.DataTable({
1472
columns: ['type', 'slices'],
1473
data: new Y.PieList()
1477
pies.data.load(function () {
1479
pies.render('#pie-cart');
1481
// The new PieModel's save() method is called, notifying the server
1482
pies.addRow({ type: 'pecan', slices: 8 });
1484
// Let us eat some pie!
1485
pies.modifyRow('lemon meringue', { slices: 5 });
1489
<h3 id="scrolling">Scrolling</h3>
1492
<strong>Note:</strong> Scrolling is not currently supported on the Android
1497
Scrolling functionality can be added to <code>Y.DataTable</code> by including
1498
<code>datatable-scroll</code> module in your <code>use()</code>. <code>datatable-scroll</code> is
1499
<strong>NOT</strong> included in the <code>datatable</code> rollup module, so must be
1500
included separately.
1504
Enable scrolling by setting the <code>scrollable</code> attribute, which accepts values
1505
"x", "y", "xy", <code>true</code> (same as "xy"), or <code>false</code> (the default).
1509
Note, vertical scrolling also requires the table's <code>height</code> attribute to be
1510
set, and horizontal scrolling requires the <code>width</code> to be set.
1513
<pre class="code prettyprint">// Data from the seafoodwatch YQL table as of 3/16/2012
1515
{ "fish": "Barramundi (Imported Farmed in Open Systems)", "recommendation": "avoid" },
1516
{ "fish": "Caviar, Paddlefish (Wild caught from U.S.)", "recommendation": "avoid" },
1517
{ "fish": "Caviar, Sturgeon (Imported Wild-caught)", "recommendation": "avoid" },
1521
// Enable vertical scrolling with scrollable "y". The width is also set, but
1522
// because scrollable is not "x" or "xy", this just sets the table width.
1523
var table = new Y.DataTable({
1524
caption: 'Seafood tips for the US West Coast',
1525
columns: ['fish', 'recommendation'],
1527
scrollable: "y",
1528
height: "200px",
1529
width: "400px"
1530
}).render("#scroll");</pre>
1533
<p>This code produces this table:</p>
1535
<div id="scroll-example" class="yui3-skin-sam"></div>
1538
YUI().use('datatable-scroll', function (Y) {
1539
// Data from the seafoodwatch YQL table as of 3/16/2012
1541
{ "fish": "Barramundi (Imported Farmed in Open Systems)", "recommendation": "avoid" },
1542
{ "fish": "Caviar, Paddlefish (Wild caught from U.S.)", "recommendation": "avoid" },
1543
{ "fish": "Caviar, Sturgeon (Imported Wild-caught)", "recommendation": "avoid" },
1544
{ "fish": "Chilean Seabass", "recommendation": "avoid" },
1545
{ "fish": "Cobia (Imported Farmed)", "recommendation": "avoid" },
1546
{ "fish": "Cod, Atlantic (Trawl-caught from Canadian and U.S. Atlantic)", "recommendation": "avoid" },
1547
{ "fish": "Cod, Pacific (Imported)", "recommendation": "avoid" },
1548
{ "fish": "Crab, King (Imported)", "recommendation": "avoid" },
1549
{ "fish": "Dab, Common (Danish Seine from Iceland)", "recommendation": "avoid" },
1550
{ "fish": "Flounder (Wild-caught from U.S. Atlantic, Except Summer Flounder)", "recommendation": "avoid" },
1551
{ "fish": "Hake, White", "recommendation": "avoid" },
1552
{ "fish": "Halibut, Atlantic (Wild-caught from U.S.)", "recommendation": "avoid" },
1553
{ "fish": "Lobster, Caribbean Spiny (Brazil)", "recommendation": "avoid" },
1554
{ "fish": "Mahi Mahi (Imported Longline)", "recommendation": "avoid" },
1555
{ "fish": "Marlin, Blue (Imported)", "recommendation": "avoid" },
1556
{ "fish": "Marlin, Striped", "recommendation": "avoid" },
1557
{ "fish": "Monkfish", "recommendation": "avoid" },
1558
{ "fish": "Octopus (Philippines)", "recommendation": "avoid" },
1559
{ "fish": "Orange Roughy", "recommendation": "avoid" },
1560
{ "fish": "Plaice, American (Wild-caught from U.S. Atlantic)", "recommendation": "avoid" },
1561
{ "fish": "Pollock, Atlantic (Danish Seine and Trawl from Iceland)", "recommendation": "avoid" },
1562
{ "fish": "Salmon (Farmed including Atlantic Except U.S. Farmed in Tank Systems)", "recommendation": "avoid" },
1563
{ "fish": "Sardines, Atlantic (Mediterranean)", "recommendation": "avoid" },
1564
{ "fish": "Shad, American (U.S. Atlantic Gillnet)", "recommendation": "avoid" },
1565
{ "fish": "Shark (Except Common Thresher and Shortfin Mako, from California and Hawaii)", "recommendation": "avoid" },
1566
{ "fish": "Shrimp (Imported Farmed Except Thailand Farmed in Fully Reciruclating Systems)", "recommendation": "avoid" },
1567
{ "fish": "Shrimp (Imported Wild-Caught Except Canadian)", "recommendation": "avoid" },
1568
{ "fish": "Shrimp (Mexico Farmed in Open Systems)", "recommendation": "avoid" },
1569
{ "fish": "Skates", "recommendation": "avoid" },
1570
{ "fish": "Snapper, Red (U.S. Gulf of Mexico Wild-caught)", "recommendation": "avoid" },
1571
{ "fish": "Snapper, Red (Imported Wild-caught)", "recommendation": "avoid" },
1572
{ "fish": "Sole (Wild-caught from U.S Atlantic)", "recommendation": "avoid" },
1573
{ "fish": "Sturgeon (Imported Wild-caught)", "recommendation": "avoid" },
1574
{ "fish": "Swordfish (Imported)", "recommendation": "avoid" }
1577
var table = new Y.DataTable({
1578
caption: 'Seafood tips for the US West Coast',
1579
columns: ['fish', 'recommendation'],
1583
width: "400px" // scrollable is not set to x or xy, so no scrolling
1584
}).render("#scroll-example");
1588
<h2 id="events">DataTable Events</h2>
1591
DataTable is a composition of supporting class instances and extensions, so
1592
to centralize event reporting, it is a bubble target for its <code>data</code>
1593
ModelList as well as the View instances used for rendering.
1597
In other words, some events you may need to subscribe to using an event
1598
prefix to be notified. Often, using a wildcard prefix is the simplest
1599
method to ensure your subscribers will be notified, even if classes change.
1602
<pre class="code prettyprint">// The sort event is from an extension, so it originates from DataTable
1603
table.after('sort', function (e) { ... });
1605
// Model changes originate from the record's Model instance, propagate to the
1606
// table's ModelList, then finally to the DataTable, so they must be
1607
// subscribed with an event prefix. In this case, we'll use a wildcard
1608
// prefix.
1609
table.after('*:priceChange', function (e) { ... });</pre>
1613
DataTable generates a custom Model class with the "record" event prefix, if
1614
you want to be more specific. Otherwise, if your table uses a custom Model
1615
class for its <code>recordType</code>, you can prefix Model events with the appropriate
1619
<pre class="code prettyprint">// Allow DataTable to generate the Model class automatically
1620
var table = new Y.DataTable({
1621
columns: ['items', 'cost', 'price'],
1623
{ item: "widget", cost: 23.57, price: 47.5 },
1624
{ item: "gadget", cost: 0.11, price: 6.99 },
1629
// generated Model classes have prefix "record"
1630
table.after('record:change', function (e) { ... });
1632
// PieList uses PieModels, which have a prefix of, you guessed it, "pie"
1633
var pies = new Y.DataTable({
1634
columns: ['type', 'slices'],
1635
data: new Y.PieList()
1638
pies.on('pie:slicesChange', function (e) {
1639
if (e.target.get('type') === 'chocolate creme') {
1640
// Oh no you don't!
1647
The full list of events is included in <a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html#events">the DataTable API docs</a>.
1650
<h2 id="knownissues">Known Issues</h2>
1655
<a href="http://yuilibrary.com/projects/yui3/ticket/2529761">not
1656
currently supported on Android</a> WebKit browser.
1660
<a href="http://yuilibrary.com/projects/yui3/ticket/2531047">may not
1661
appear scrollable</a> on iOS browsers or OS X 10.7 depending on the
1662
system preference "Show scroll bars" (General).
1666
<h2 id="column-config">Appendix A: Column Configurations</h2>
1669
The properties below are supported in the column configuration objects
1670
passed in the <code>columns</code> attribute array.
1673
<div id="column-config-table" class="yui3-skin-sam">
1677
<th scope="col">Configuration</th>
1678
<th scope="col">Description</th>
1679
<th scope="col">Module</th>
1686
<pre class="code prettyprint">{ key: 'username' }</pre>
1689
Binds the column values to the named property in the <code>data</code>.
1692
Optional if <code>formatter</code>, <code>nodeFormatter</code>, or <code>cellTemplate</code>
1693
is used to populate the content.
1695
<p>It should not be set if <code>children</code> is set.</p>
1697
The value is used for the <code>_id</code> property unless the <code>name</code>
1698
property is also set.
1701
<td><code>datatable-base</code></td>
1706
<pre class="code prettyprint">{ name: 'fullname', formatter: ... }</pre>
1710
Use this to assign a name to pass to <code>table.getColumn(NAME)</code>
1711
or style columns with class "yui3-datatable-col-NAME" if a
1712
column isn't assigned a <code>key</code>.
1715
The value is used for the <code>_id</code> property.
1718
<td><code>datatable-base</code></td>
1723
<pre class="code prettyprint">{ field: 'fullname', formatter: ... }</pre>
1726
<p>An alias for <code>name</code> for backward compatibility.</p>
1728
<td><code>datatable-base</code></td>
1733
<pre class="code prettyprint">{
1734
name: 'checkAll',
1735
id: 'check-all',
1741
Overrides the default unique id assigned <code><th id="HERE"></code>.
1744
<em>Use this with caution</em>, since it can result in
1745
duplicate ids in the DOM.
1748
<td><code>datatable-base</code></td>
1753
<pre class="code prettyprint">{ key: 'MfgPrtNum', label: 'Part Number' }</pre>
1756
<p>HTML to populate the header <code><th></code> for the column.</p>
1758
<td><code>datatable-base</code></td>
1764
Used to create stacked headers.
1765
<a href="#nested">See the example above</a>.
1769
Child columns may also contain <code>children</code>. There is no limit
1770
to the depth of nesting.
1774
Columns configured with <code>children</code> are for display only and
1775
<strong>should not</strong> be configured with a <code>key</code>.
1776
Configurations relating to the display of data, such as
1777
<code>formatter</code>, <code>nodeFormatter</code>, <code>emptyCellValue</code>, etc. are
1781
<td><code>datatable-base</code></td>
1786
<pre class="code prettyprint">{
1787
key : 'forecast',
1788
label: '1yr Target Forecast',
1789
abbr : 'Forecast'
1793
<p>Assigns the value <code><th abbr="HERE"></code>.</p>
1795
<td><code>datatable-base</code></td>
1798
<td>headerTemplate</td>
1800
<pre class="code prettyprint">{
1802
'<th id="{id}" ' +
1803
'title="Unread" ' +
1804
'class="{className}" ' +
1805
'{_id}>&#9679;</th>'
1810
Overrides the default
1811
<a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.HeaderView.html#property_CELL_TEMPLATE">CELL_TEMPLATE</a>
1812
used by <code>Y.DataTable.HeaderView</code> to render the header cell
1813
for this column. This is necessary when more control is
1814
needed over the markup for the header itself, rather than
1819
Use the <code>label</code> configuration if you don't need to
1820
customize the <code><th></code> iteself.
1824
Implementers are strongly encouraged to preserve at least
1825
the <code>{id}</code> and <code>{_id}</code> placeholders in the custom value.
1828
<td><code>datatable-base</code></td>
1831
<td>cellTemplate</td>
1833
<pre class="code prettyprint">{
1834
key: 'id',
1836
'<td class="{className}">' +
1837
'<input type="checkbox" ' +
1838
'id="{content}">' +
1839
'</td>'
1844
Overrides the default
1845
<a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.BodyView.html#property_CELL_TEMPLATE">CELL_TEMPLATE</a>
1846
used by <code>Y.DataTable.BodyView</code> to render the data cells
1847
for this column. This is necessary when more control is
1848
needed over the markup for the <code><td></code> itself, rather than
1852
<td><code>datatable-base</code></td>
1858
Used to customize the content of the data cells for this
1863
<a href="#formatters">See the example above</a>
1866
<td><code>datatable-base</code></td>
1869
<td>nodeFormatter</td>
1872
Used to customize the content of the data cells for this
1877
<a href="#formatters">See the example above</a>
1880
<td><code>datatable-base</code></td>
1883
<td>emptyCellValue</td>
1885
<pre class="code prettyprint">{
1886
key: 'price',
1887
emptyCellValue: '???'
1892
Provides the default value to populate the cell if the data
1893
for that cell is <code>undefined</code>, <code>null</code>, or an empty string.
1896
<td><code>datatable-base</code></td>
1901
<pre class="code prettyprint">{
1902
key: 'preview',
1908
Skips the security step of HTML escaping the value for cells
1909
in this column. This is also necessary if <code>emptyCellValue</code>
1910
is set with an HTML string.
1913
<code>nodeFormatter</code>s ignore this configuration. If using a
1914
<code>nodeFormatter</code>, it is recommended to use
1915
<a href="http://yuilibrary.com/yui/docs/api/classes/Escape.html#method_html">Y.Escape.html()</a>
1916
on any user supplied content that is to be displayed.
1919
<td><code>datatable-base</code></td>
1924
<pre class="code prettyprint">{
1925
key: 'symbol',
1926
className: 'no-hide'
1931
A string of CSS classes that will be added to the <code><td></code>'s
1932
<code>class</code> attribute.
1936
Note, all cells will automatically have a class in the
1937
form of "yui3-datatable-col-KEY" added to the <code><td></code>, where
1938
KEY is the column's configured <code>name</code>, <code>key</code>, or <code>id</code> (in
1939
that order of preference).
1942
<td><code>datatable-base</code></td>
1947
<pre class="code prettyprint">{ key: 'a', width: '400px' },
1948
{ key: 'b', width: '10em' }</pre>
1952
Adds a style <code>width</code> setting to an associated <code><col></code>
1953
element for the column.
1957
Note, the assigned width will not truncate cell content, and
1958
it will not preserve the configured width if doing so would
1959
compromise either the instance's <code>width</code> configuration or
1960
the natural width of the table's containing DOM elements.
1964
If absolute widths are required, it can be accomplished with
1965
some custom CSS and the use of a <code>cellTemplate</code>, or
1966
<code>formatter</code>. See
1967
<a href="http://yuilibrary.com/yui/docs/api/modules/datatable-column-widths.html">the
1968
description of <code>datatable-column-widths</code></a> for an example
1972
<td><code>datatable-column-widths</code></td>
1977
<pre class="code prettyprint">{ key: 'lastLogin', sortable: true }</pre>
1981
Used when the instance's <code>sortable</code> attribute is set to
1982
"auto" (the default) to determine which columns will support
1983
user sorting by clicking on the header.
1986
If the instance's <code>sortable</code> attribute is set, this
1987
configuration is ignored.
1990
<td><code>datatable-sort</code></td>
1995
<pre class="code prettyprint">{
1996
label: 'Name',
1997
sortFn: function (a, b, desc) {
1998
var an = a.get('lname') + b.get('fname'),
1999
bn = a.get('lname') + b.get('fname'),
2000
order = (an > bn) ? 1 : -(an < bn);
2002
return desc ? -order : order;
2004
formatter: function (o) {
2005
return o.data.lname + ', ' + o.data.fname;
2011
Allows a column to be sorted using a custom algorithm. The
2012
function receives three parameters, the first two being the
2013
two record Models to compare, and the third being a boolean
2014
<code>true</code> if the sort order should be descending.
2017
The function should return <code>-1</code> to sort <code>a</code> above <code>b</code>, <code>-1</code>
2018
to sort <code>a</code> below <code>b</code>, and <code>0</code> if they are equal. Keep in
2019
mind that the order should be reversed when <code>desc</code> is
2023
The <code>desc</code> parameter is provided to allow <code>sortFn</code>s to
2024
always sort certain values above or below others, such as
2025
always sorting <code>null</code>s on top.
2028
<td><code>datatable-sort</code></td>
2034
(<strong>read-only</strong>) If a column is sorted, this
2035
will be set to <code>1</code> for ascending order or <code>-1</code> for
2036
descending. This configuration is public for inspection,
2037
but can't be used during DataTable instantiation to set the
2038
sort direction of the column. Use the table's
2039
<a href="http://yuilibrary.com/yui/docs/api/classes/DataTable.html#attr_sortBy">sortBy</a>
2043
<td><code>datatable-sort</code></td>
2049
(<strong>read-only</strong>) The unique identifier assigned
2050
to each column. This is used for the <code>id</code> if not set, and
2051
the <code>_id</code> if none of <code>name</code>, 'field<code>, </code>key<code>, or </code>id` are
2055
<td><code>datatable-base</code></td>
2061
(<strong>read-only</strong>) A unique-to-this-instance name
2062
used extensively in the rendering process. It is also used
2063
to create the column's classname, as the input name
2064
<code>table.getColumn(HERE)</code>, and in the column header's
2065
<code><th data-yui3-col-id="HERE"></code>.
2068
The value is populated by the first of <code>name</code>, <code>field</code>,
2069
<code>key</code>, <code>id</code>, or <code>_yuid</code> to have a value. If that value
2070
has already been used (such as when multiple columns have
2071
the same <code>key</code>), an incrementer is added to the end. For
2072
example, two columns with <code>key: "id"</code> will have <code>_id</code>s of
2073
"id" and "id2". <code>table.getColumn("id")</code> will return the
2074
first column, and <code>table.getColumn("id2")</code> will return the
2078
<td><code>datatable-base</code></td>
2084
(<strong>read-only</strong>) Used by
2085
<code>Y.DataTable.HeaderView</code> when building stacked column
2089
<td><code>datatable-base</code></td>
2095
(<strong>read-only</strong>) Used by
2096
<code>Y.DataTable.HeaderView</code> when building stacked column
2100
<td><code>datatable-base</code></td>
2106
(<strong>read-only</strong>) Assigned to all columns in a
2107
column's <code>children</code> collection. References the parent
2111
<td><code>datatable-base</code></td>
2117
(<strong>read-only</strong>) Array of the <code>id</code>s of the
2118
column and all parent columns. Used by
2119
<code>Y.DataTable.BodyView</code> to populate <code><td headers="THIS"></code>
2120
when a cell references more than one header.
2123
<td><code>datatable-base</code></td>
2129
<h2 id="formatter-props">Appendix B: Formatter Argument Properties</h2>
2132
The properties below are found on the object passed to <code>formatter</code>
2133
functions defined in a column configuration. See
2134
<a href="#nodeformatter-props">Appendix C</a> for the object properties
2135
passed to <code>nodeFormatter</code>s.
2138
<div id="formatter-props-table" class="yui3-skin-sam">
2142
<th scope="col">Property</th>
2143
<th scope="col">Description</th>
2148
<td><code>value</code></td>
2150
<pre class="code prettyprint">formatter: function (o) {
2151
// assumes a numeric value for this column
2152
return '$' + o.value.toFixed(2);
2157
The raw value from the record Model to populate this cell.
2158
Equivalent to <code>o.record.get(o.column.key)</code> or
2159
<code>o.data[o.column.key]</code>.
2164
<td><code>data</code></td>
2166
<pre class="code prettyprint">formatter: function (o) {
2167
return o.data.lname + ', ' + o.data.fname;
2172
The Model data for this row in simple object format.
2177
<td><code>record</code></td>
2179
<pre class="code prettyprint">formatter: function (o) {
2180
return '<a href="/service/' + o.record.get('id') + '"> +
2181
o.value + '</a>';
2186
The Model for this row.
2191
<td><code>column</code></td>
2193
<pre class="code prettyprint">formatter: function (o) {
2194
// Use a custom column property
2195
var format = o.column.dateFormat || '%D';
2197
return Y.DataType.Data.format(o.value, format);
2202
The column configuration object.
2207
<td><code>className</code></td>
2209
<pre class="code prettyprint">formatter: function (o) {
2210
if (o.value < 0) {
2211
o.className += 'loss';
2217
A string of class names to add <code><td class="HERE"></code> in
2218
addition to the column class and any classes in the
2219
column's <code>className</code> configuration.
2224
<td><code>rowIndex</code></td>
2226
<pre class="code prettyprint">formatter: function (o) {
2227
return (o.rowIndex + 1) + ' - ' + o.value;
2232
The index of the current Model in the ModelList.
2233
<em>Typically</em> correlates to the row index as well.
2238
<td><code>rowClass</code></td>
2240
<pre class="code prettyprint">formatter: function (o) {
2241
if (o.value < 0) {
2242
o.rowClass += 'loss';
2248
A string of css classes to add <code><tr class="HERE"><td...</code>.
2252
This is useful to avoid the need for <code>nodeFormatter</code>s to add
2253
classes to the containing row.
2261
<h2 id="nodeformatter-props">Appendix C: nodeFormatter Argument Properties</h2>
2264
The properties below are found on the object passed to <code>nodeFormatter</code>
2265
functions defined in a column configuration. See
2266
<a href="#formatter-props">Appendix B</a> for the object properties
2267
passed to <code>formatter</code>s.
2270
<pre class="code prettyprint">// Reference nodeFormatter
2271
nodeFormatter: function (o) {
2272
if (o.value < o.data.quota) {
2273
o.td.setAttribute('rowspan', 2);
2274
o.td.setAttribute('data-term-id', this.record.get('id'));
2276
o.td.ancestor().insert(
2277
'<tr><td colspan"3">' +
2278
'<button class="term">terminate</button>' +
2279
'</td></tr>',
2283
o.cell.setContent(o.value);
2287
<div id="nodeformatter-props-table" class="yui3-skin-sam">
2291
<th scope="col">Property</th>
2292
<th scope="col">Description</th>
2297
<td><code>td</code></td>
2298
<td>The <code><td></code> Node for this cell.</td>
2301
<td><code>cell</code></td>
2304
If the cell <code><td></code> contains an element with class
2305
"yui3-datatable-liner", this will refer to that Node.
2306
Otherwise, it is equivalent to <code>o.td</code> (default behavior).
2310
By default, liner elements aren't rendered into cells, but
2311
to implement absolute column widths, some cell liner
2312
element with <code>width</code> and <code>overflow</code> style is required
2313
(barring a table style of <code>table-layout: fixed</code>). This may
2314
be applied to the columns <code>cellTemplate</code> configuration or
2315
to the <code>bodyView</code> instance's <code>CELL_TEMPLATE</code> for all
2320
Generally, the liner, if present, corresponds to where the
2321
content should go, so use <code>o.cell</code> to add content and
2322
<code>o.td</code> to specifically work with the <code><td></code> Node.
2327
<td><code>value</code></td>
2329
The raw value from the record Model to populate this cell.
2330
Equivalent to <code>o.record.get(o.column.key)</code> or
2331
<code>o.data[o.column.key]</code>.
2335
<td><code>data</code></td>
2336
<td>The Model data for this row in simple object format.</td>
2339
<td><code>record</code></td>
2340
<td>The Model for this row.</td>
2343
<td><code>column</code></td>
2344
<td>The column configuration object.</td>
2347
<td><code>rowIndex</code></td>
2349
The index of the current Model in the ModelList.
2350
<em>Typically</em> correlates to the row index as well.
2357
YUI.add('datatable-node', function (Y) {
2358
Y.Plugin.DataTable = Y.Base.create('datatable', Y.DataTable, [], {
2359
initializer: function (config) {
2360
var columns = config.host.all('thead th').get('text'),
2361
count = columns.length,
2365
config.host.all('tbody td').each(function (node, i) {
2366
var record = (i % count) ?
2367
data[data.length - 1] :
2368
(data[data.length] = {});
2369
record[columns[i % count]] = node.getContent();
2372
for (i = columns.length - 1; i >= 0; --i) {
2373
columns[i] = { key: columns[i], allowHTML: true }
2383
config.host.replace(this.get('boundingBox'));
2389
Y.Node.ATTRS.datatable = {
2390
setter: function (val) {
2395
this.plug(Y.Plugin.DataTable, val);
2398
}, '0.1', { requires: ['datatable-base', 'node-pluginhost'] });
2399
YUI({ filter: 'raw' }).use('datatable-node', 'datatable-sort', function (Y) {
2400
Y.one('#column-config-table table').set('datatable', {
2401
sortable: ['Configuration', 'Module']
2403
Y.one('#formatter-props-table table').set('datatable', true);
2404
Y.one('#nodeformatter-props-table table').set('datatable', true);
2411
<div class="yui3-u-1-4">
2412
<div class="sidebar">
2414
<div id="toc" class="sidebox">
2416
<h2 class="no-toc">Table of Contents</h2>
2422
<a href="#getting-started">Getting Started</a>
2425
<a href="#migration-intro">Upgrading from version 3.4.1 or older?</a>
2428
<a href="#using">DataTable Basics</a>
2431
<a href="#columns">Column Configuration</a>
2434
<a href="#nested">Stacked Column Headers</a>
2437
<a href="#formatters">Formatting Cell Data</a>
2440
<a href="#formatter-function">Setting content with <code>formatter</code> functions</a>
2443
<a href="#nodeformatters">Setting content with <code>nodeFormatter</code> functions</a>
2446
<a href="#formatter-vs-nodeformatter">Why <code>formatter</code> and <code>nodeFormatter</code>?</a>
2449
<a href="#formatters-vs-empty">Formatters vs. <code>emptyCellValue</code></a>
2456
<a href="#data">Table Data Configuration</a>
2459
<a href="#recordtype">Specifying the Record Model</a>
2462
<a href="#modellist">The <code>data</code> ModelList</a>
2465
<a href="#getting-data">Getting Remote Table Data</a>
2470
<a href="#features">DataTable Modules and Features</a>
2473
<a href="#base">Features in <code>DataTable.Base</code></a>
2476
<a href="#datatable-message">Table Messages</a>
2479
<a href="#colwidths">Column Width Configuration</a>
2482
<a href="#sorting">Column sorting</a>
2485
<a href="#customsort">Custom Sorting</a>
2488
<a href="#sortapi">Sorting Methods</a>
2491
<a href="#sortby">The <code>sortBy</code> Attribute</a>
2494
<a href="#sortevent">The <code>sort</code> Event</a>
2499
<a href="#mutation">Table Mutation APIs (<code>addRow</code>, etc)</a>
2502
<a href="#column-mutation">Column Mutation Methods</a>
2505
<a href="#row-mutation">Row Mutation Methods</a>
2510
<a href="#scrolling">Scrolling</a>
2515
<a href="#events">DataTable Events</a>
2518
<a href="#knownissues">Known Issues</a>
2521
<a href="#column-config">Appendix A: Column Configurations</a>
2524
<a href="#formatter-props">Appendix B: Formatter Argument Properties</a>
2527
<a href="#nodeformatter-props">Appendix C: nodeFormatter Argument Properties</a>
2535
<div class="sidebox">
2537
<h2 class="no-toc">Examples</h2>
2541
<ul class="examples">
2544
<li data-description="This example illustrates simple DataTable use cases.">
2545
<a href="datatable-basic.html">Basic DataTable</a>
2550
<li data-description="DataTable loaded with JSON data from a remote webservice via DataSource.Get">
2551
<a href="datatable-dsget.html">DataTable + DataSource.Get + JSON Data</a>
2556
<li data-description="DataTable loaded with XML data from a remote webservice via DataSource.IO.">
2557
<a href="datatable-dsio.html">DataTable + DataSource.IO + XML Data</a>
2562
<li data-description="Custom format data for display.">
2563
<a href="datatable-formatting.html">Formatting Row Data for Display</a>
2568
<li data-description="DataTable with nested column headers.">
2569
<a href="datatable-nestedcols.html">Nested Column Headers</a>
2574
<li data-description="DataTable with column sorting.">
2575
<a href="datatable-sort.html">Column Sorting</a>
2580
<li data-description="DataTable with vertical and/or horizontal scrolling rows.">
2581
<a href="datatable-scroll.html">Scrolling DataTable</a>
2593
<div class="sidebox">
2595
<h2 class="no-toc">Examples That Use This Component</h2>
2599
<ul class="examples">
2616
<li data-description="Shows how to instantiate multiple Panel instances, and use nested modality to interact with a Datatable.">
2617
<a href="../panel/panel-form.html">Creating a Modal Form</a>
2630
<script src="../assets/vendor/prettify/prettify-min.js"></script>
2631
<script>prettyPrint();</script>