Using YUI DataTable with Rails
February 7th, 2009 byI am currently working on an Rails app that integrates the YUI dataTable, and in going through the tutorials I noticed they are all assume a PHP back-end. I also saw a number of people asking how to get this to work with a Rails controller, so I thought I’d write up my experience in the hopes that it helps someone else. For basic info about setting up the dataTable, refer to the YUI site, linked above. I’m also going to try to clarify a few things that I found a bit obscure.
To create a dataTable you have to define a few basic ingredients:
- A dataSource. This defines where the info in the table comes from, and what format it is returned in. I’m using JSON.
- A schema that you define. This is a part of the dataSource and is essentially a map to your data. The schema tells the table where to find the field values.
- An array of column definitions. You supply the name and “key” of each column and any additional information, such as whether it is editable (and if so, which editor to use) and how to format the data inside the column if you don’t want to just spit it out directly.
Let’s start with a dataSource. In this example, we’re making a table of tasks, so I want to hit my tasks controller to return the data. Standard Rails controller action. In the code snippet below,
- in line 1, I supply a URL (note that the url ends in .json, and in my controller I have a responds_to block which constructs my json response).
- In line 2, I’m telling the dataSource — hey, you’re gonna get some JSON.
- And line 3, is where we define the responseSchema, which has two critical parts: the resultsList and the fields.
var dataSource = new YAHOO.util.XHRDataSource("/projects/13/elements/21/tasks.json");
dataSource.responseType = YAHOO.util.XHRDataSource.TYPE_JSON;
dataSource.responseSchema = {
resultsList: "Resources.data",
fields: [
{key:"task.id"},
{key:"task.status"},
{key:"task.percent_complete"},
{key:"task.description"},
{key:"task.due_date", parser:date}
]
}
Let me be clear since I got hung up on this a bit. You as the application developer are responsible for two things. One, constructing your response — in other words, you can build your JSON response any way you want, with any keys, values and hierarchical structure that make sense (though it will help you to think it through and standardize it, Satyam has some good info on that here). And two, telling your dataSource how to navigate your response: i.e. — where do find what the data you’re looking for (the needle) in the response (the haystack of JSON)? This is the schema, the map of your data.
Controller code that creates my custom JSON:
# tasks_controller.rb
def index
respond_to do |format|
format.json{
tasks = []
@tasks.each do |task|
task_container = {}
task_container = task
task_container['editable_by_user'] = permission.edit? # some metadata I use
task_container['deletable_by_user'] = permission.delete?
task_container['resource_name'] = "task"
tasks << task_container
end
data = {"Resources" => {"data" => tasks}}
render :json => data.to_json
}
end
end
And just for fun, here’s a look at the JSON my controller gives me back when I hit this url ‘/projects/13/elements/21/tasks.json’.
The JSON:
{"Resources": {"data": [{"task": {"status": "not_started", "started_on": null, "updated_at": "2009-02-07T22
:03:18Z", "project_id": 13, "percent_complete": null, "high_priority": null, "element_id": 32, "deletable_by_user"
: true, "completed_on": null, "editable_by_user": true, "element_title": "looking good", "id": 50, "created_by_id"
: 7, "resource_name": "task", "description": "Pass the stimulus bill", "assignments": [], "due_date"
: "", "users": [], "resource_url": "/projects/13/elements/32/tasks/50", "due": null, "created_at": "2009-02-07T22
:03:18Z"}}, {"task": {"status": "not_started", "started_on": null, "updated_at": "2009-02-07T22:03:39Z"
, "project_id": 13, "percent_complete": null, "high_priority": null, "element_id": 32, "deletable_by_user"
: true, "completed_on": null, "editable_by_user": true, "element_title": "looking good", "id": 51, "created_by_id"
: 7, "resource_name": "task", "description": "Negotiate without pre-conditions", "assignments": [], "due_date"
: "", "users": [], "resource_url": "/projects/13/elements/32/tasks/51", "due": null, "created_at": "2009-02-07T22
:03:39Z"}}]}}
So that’s it! I’ve defined this JSON array and built it, then returned it from the controller when I get a .json request.
Now that you’ve seen the response, take another look at the responseSchema (you created above) and the two properties that you set:
- ResultsList. Notice it is set to “Resources.data”, which are the JSON keys I used. It uses dot-syntax to point to array of tasks in my json.
- Fields. Again using dot syntax, and having the ResultsList array to navigate through, it can pull the specific values it wants from the list; so ‘task.status’, ‘task.started_on’, etc., will retrieve those values from the response.
Make sense?
You are now one step away from being able to see your table. So, create your column definitions, an array of data about each column in the table. This is also where you can specify formatting and editing information (not covered in this article).
var columnDefinitions = [
{key:"task.status",formatter:"formatPriority", sortable:true},
{key:"task.percent_complete", label:"Percent Complete", sortable:true},
{key:"task.description", label:"Description"},
{key:"task.due_date", label:"Due Date", editable:true,sortable: "true",formatter:YAHOO.widget.DataTable.formatDate, editor: new YAHOO.widget.DateCellEditor({resource:'task', updateParams:"task[due]"})}
];
Notice that each column definition has a key: this key must be accessible in your JSON, AND it must be defined as a field.
And then you create your table. The first argument is the id of a div on the page to which the table will be attached, the last is an optional configuration hash (pagination, anyone?).
var dataTable = new YAHOO.widget.DataTable("project_tasks", columnDefinitions, dataSource, optionalConfigurationHash);
I hope this is helpful to get you started with the YUI dataTable on Rails. I may do further posts on XHR editing of individual cells in a dataTable using Rails.

June 23rd, 2009 at 11:48 pm
if you show the result with an example will be more useful…
July 28th, 2009 at 6:10 pm
how do you submit the datatable values back to the controller. I can do JavaScript to pick up the old and new values, but how to submit it. I am sure there are XHR ways, but if you have a pointer will b great.
June 14th, 2010 at 10:58 am
Have you taken this any further – we are particularly interested due to difficulties trying to freeze table headers with Prototype.