RJS Element and Collection Proxies

Background

Some powerful new features have been added to Rails RJS Templates. What are these new features? They are called element and collection proxies.

Element Proxies

First, from Wikipedia, the definition of the Proxy pattern:

A proxy, in its most general form, is a class functioning as an interface to another thing.

So, in the case of RJS templates, the proxy is functioning as an interface to a JavaScript DOM object. The syntax is quite similar to the syntax of the original RJS templates, except that we use the [] operator on the page object within the template. So, if we wanted to hide the DOM element with id header, we'd use the following code:

1
2

page['header'].hide

You can also use symbols, so passing in :header will also work.

Currently there is support for all of the RJS methods that you are already familiar with like replace_html, replace, visual_effect, show and hide. In addition, there is an interesting new method named reload, which will call replace on the element and replace the element's content with the rendered output of a partial of the same name. Example:

1
2

page['header'].reload

Is equivalent to

1
2

page['header'].replace :partial => 'header'

The proxy will also correctly pass through other Prototype methods that previously had to be called using page.call, such as remove_class_name.

So far the proxies may just look like a matter of semantics, however, when combined with the new select method, the results are very powerful.

Collection Proxies

The new select method returns an array of DOM objects. select takes as an argument a CSS based selector and returns an array of DOM objects matching that selector. So, to get all paragraphs within the <div> with id content, we would use:

1
2

page.select('#content p')

Now combine this with the enumerable methods available through the collection proxy and you can do things like:

1
2
3
4

page.select('#content p').each do |element|
  element.hide
end

All <p> elements within the <div> with id content will be hidden.

Not only is it easy to iterate through the elements of the collection, but Rick Olson, the newest Rails core team member, went out and got all sorts of other enumerable methods that Prototype supports working. I'm going to leave those as an exercise for you to explore. You can start with the changeset.

Summary

The new element and collection proxies are a very nice and powerful addition to RJS. They allow us more flexibilty and we now have to write even less JavaScript. They also provide a nicer syntax for calling existing Prototype methods on DOM elements from RJS templates.

6 Responses to “RJS Element and Collection Proxies”

  1. Josh Adams Says:
    How does one get all this working? I've done a freeze\_edge and an update\_javascripts, but page['foo'].hide still generates $('foo').hide(); which doesn't work. Any hints?
  2. Cody Fauser Says:
    The generated JavaScript you posted is correct. You have to make sure you have a DOM element with `id` of *foo* and you also need to make sure that you are including the javascripts in your project. Does this work?
    
    
    page.hide 'foo'
    Check out my original [article](http://www.codyfauser.com/articles/2005/11/20/rails-rjs-templates) if you need help getting started.
  3. Jesse Says:
    Great posts
  4. Nate Says:
    Codey, you may already know this, but I couldn't access your site for the last few days. I'm glad to see it up now, keep up the great tutorials.
  5. Sunder Says:
    This is sweet, I love the reload and the select method. I have been frustrated before having to call a partial from an rjs , which was not DRY, so this is perfect!! The select - collection is nice too, just name the tag's with a pattern and the collection proxies will take care of the rest. Thanks for a great post!
  6. Peter Says:
    page.select(".nummer").each do |element| element.hide end I have tried this with a class like David on the blog. It works but its very slow. It takes 5 seconds to render. Any ideas why?

Sorry, comments are closed for this article.