Some powerful new features have been added to Rails RJS Templates. What are these new features? They are called element and collection 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.
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.
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.
Sorry, comments are closed for this article.
March 23rd, 2006 at 03:54 PM 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?
March 23rd, 2006 at 04:13 PM 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'March 24th, 2006 at 02:48 AM Great posts
March 28th, 2006 at 09:45 PM 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.
March 29th, 2006 at 06:23 AM 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!
March 29th, 2006 at 11:18 PM 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?