What’s a widget?

I have no idea. I’m sure the cool kids have a better name for it these days, but we’ll just call ‘em widgets for now. When we draw a wireframe of a web app with a box around some bit of functionality, we tend to refer to that thing as a ’widget’.

Taking this a step further, while a widget is often thought of as a discreet piece of functionality, we also tend to think of it as being portable. That lovely little widget is just so great, let’s share it with the world! Can’t we just “drop that in” to another website? Yes we can!

JavaScript widgets

Rendering the HTML content of our widget on a separate “consuming” web application is typically done with JavaScript. If our widget includes only static content, it’s very simple to render that content remotely. Ilya Grigorik’s post on Creating JavaScript Widgets in Rails demonstrates this technique, essentially wrapping each line of HTML output in a call to document.write.

Functional Javascript widgets

What if our widgets actually do stuff? How can we build fully-functional widgets with Rails that can be consumed by other websites? Here’s one way to do it…

1. Create the feature that you want to ‘widgetize’ with Rails

Let’s say you’d like to support CRUD actions on content for your awesome home-grown blog app. Create your model, controller, view(s) and routes as usual. Don’t forget your tests. Set up some nice model validation and build your forms The Rails Way. Don’t forget to use the route_url route name instead of the route_path name in the form actions, since we’ll be interacting with this form from a different host eventually.

2. AJAX, baby!

I prefer jQuery over Prototype, so I’d suggest using the jquery-rails gem in addition to the latest version of jQuery.

Rails has made it very convenient to create RESTful widgets services. However, as soon as we want to interact with a RESTful service using AJAX, we have to come up with our own pattern for our views. We often want to send back content to be rendered as HTML. We’ll also need a way to communicate success or failure along with specific error messages we may want to render in the widget. Additionally, we often need to redirect our users to new pages after they complete a certain step.

Peter Bui wrote js_message that solves this pattern nicely. Her’s a quick example:

3. Cross-domain JSON with JSONP

JSONP is an awesome hack. Here is a great explanation of what JSONP is on Stack Overflow. Now that we know what it is, Kevin Chiu shows us how to use JSONP in a Rails3 controller.

We’re now using JSONP, but we’re still getting these strange same origin policy errors. No worries! Here’s how we can allow multiple access control requests in Rails.

This is great, we’ve got a widget that pulls content in asynchronously across domains. Unfortunately, the content we’re getting is just JSON. We want HTML!

4. Square peg in a round hole

Let’s render our erb template to a string, then wrap it in a tasty JSON envelope! We’d have to take care of quotes and newlines though, to make it JSON safe…

Example:

(Hat tip to JSON Lint for testing my JSON output)

5. Finally, the widget view

Then all the consuming web app needs to do in order to render your awesome widget, is drop in this JavaScript file:

6. Profit!

Now you’ve got fully functional widgets in Rails that you can let other web applications drop into their site. Surely it won’t be long before the cash starts rolling in.



Discussion, links, and tweets

Follow me on Twitter for more musings from the ether.

© 2007-2015 Brian Doll