Pragmatic Rails: Let’s do AJAX-backed Sidebar Widgets right, Jim!
Saturday, November 20th, 2010Days ago I explained how to write a sidebar widget in Rails, using the view component framework Cells. This was fun.

Clicking a tag leads to a page reload, where the Recent posts list displays items matching the tag, only. It worked great, however, each click needs a real HTTP request and a reload – let’s use AJAX to handle that.
Rails and AJAX? Apotomo!
Widgets+Rails usually means you’re better off using Apotomo , a new kid on the block. Apotomo is a web component framework for Rails, I will officially announce it in a separate post soon.
Let’s discuss how I converted the Recent posts cell into an interactive widget. If that’s too brief, there is a detailed in-depth tutorial here, just follow the links at Learn.
Check out the repository of this example app if you wanna play around.
Getting a cell interactive
We need the Apotomo gem, so I put it in the Gemfile.
gem 'rails', '3.0.1' gem 'cells' gem 'apotomo', "~>1.0" # ... and so on
I would never forget to run bundle install, Freddi!
In order to make a cell a widget, I inherit from Apotomo::Widget.
class PostsWidget < Apotomo::Widget def display @tag = param(:tag) @posts = @tag ? Post.tagged_with(@tag) : Post.recent render end def tag_cloud @tags = Post.tag_counts_on(:tags) render end end
Nothing really changed here, so far.
Note that deriving things from Widget doesn’t involve statefulness or anything – it’s just a nestable cell now, being aware to Apotomo’s events. Right, Ryan?
Widgets are cells
The assets layout slightly changed. Here’s how my app/cells directory now looks.
|-- posts_widget | |-- display.html.haml | `-- tag_cloud.html.haml `-- posts_widget.rb
Some names changed, but we still got our views in a separate directory. Widgets also reside in app/cells, there’s no need to push another folder into Rails.
Rendering a widget
After these changes, rendering the widget turns out to be fucking simple, too.
%html
%head
%title "The Incredible Cells Blog"
%body
#sidebar
= render_widget 'sidebar-posts'I just call #render_widget where I used to call #render_cell in the application.html.haml layout.
The call referes to the widget id which is defined in the controller’s widget tree. Let’s see how that works, so we can render the component.
Messing up the widget tree
Usually, widget trees are declared on the controller class layer.
class PostsController < ApplicationController include Apotomo::Rails::ControllerMethods has_widgets do |root| root << widget(:posts_widget, 'sidebar-posts') end
Just include the necessary module and setup the tree using the has_widgets method. Notice how I refer to the widget class first, then I assign the id.
Wow- this already renders the Recent posts box! The #render_widget helper automatically invokes the #display state of the widget.
Triggering events
Clicking a tag still does a real request. As I want an AJAX call here, I change the tag_cloud.html.haml view a bit.
#tag-cloud
- tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class|
= link_to tag.name, "", :class => css_class,
'data-event-url' => url_for_event(:tagClicked,
:tag => tag.name)
:javascript
$("#tag-cloud a").click(function(e) {
$.ajax({url: $(this).attr("data-event-url")});
return false;
});The first three lines didn’t change at all. However, two new steps involved here.
- First we set an attribute in each clickable tag link. The
#url_for_eventcomputes some url needed to trigger the:tagClickedevent in Rails.
- Second a small jQuery script catches click events and fires an AJAX request to the “event url“. This is that unobstrusive Javascript everybody’s talking about.
What we need to do now is catching the :tagClicked event in the ruby world and update the item list in the browser.
Luckily, Apotomo saves us from any routing and dispatching.
Catching events
As Apotomo triggers the event in the widget tree, the widget classes are one place to define observers.
class PostsWidget < Apotomo::Widget responds_to_event :tagClicked, :with => :filter def filter replace :state => :display end def display # ... and so on
I love Apotomo’s simple event system.
Again, two new steps.
- Calling
responds_to_eventsets the observer. In case of fire, it invokes the#filterstate method.
- The
#filterstate itself just calls the#displaystate which collects posts and renders. The#replacehelper method simply wraps the rendered view in a jQuery replace statement. Note that you may do that yourself – it’s up to you to emit any Javascript.
Now, the tag filtering works in the browser.
That’s all we need to write in order to have an AJAXed widget! It simply works, without any magic at all.
Apotomo is stable. Use it.
The framework we used here has been around for years but evolved from a “Model-driven architecture beast” into a small, stable widget framework based on Cells.
It is meant for RIA projects, dashboards, web desktops, well, Apotomo is here for helping you writing great widget-based web frontends, in a monolithic Rails environment.

