开发者

Using Unobtrusive JavaScript to Update an Element

As you know, when you upgrade from Rails 2 to 3 you replace this:

link_to_remote "more", :url => {...}

with this:

link_to "more", {...}, :remote => true

But how do you handle the :update option in link_to_remote? In Railscast #205 Ryan Bates demonstrates link_to with :remote and a server response that includes JavaScript code to update a particular element in a page, but this practice seems wrong to me. I want my server's response to be a simple HTML fragment which is easy to test and which can be used by different pages (clients) in different ways. I don't think the server should have to know the ID of the target element on the requesting page as it ties the action to the page (a mini-client) and therefore makes it less ge开发者_运维技巧neral (it also feels uglier than a pure HTML response).

So, to be explicit, is there a way to do something like this:

link_to_remote "more", :url => {...}, :update => "products-list"

with Rails 3 and UJS? Or do I have to write JavaScript to capture the server's HTML response and insert it into the right element on the page?

If the latter, please describe the best approach (can link_to's :remote option be used at all?).


I'm not 100% sure that this is the Rails-endorsed way to do it, but I've found a solution that works and seems pretty clean. Let's say we have a page that lists the ten most popular products in our database. At the end is a link to load all remaining products via AJAX:

<ul id="products-list">
  <li>...</li>
  <li>...</li>
  <li>...</li>
  ...
</ul>
<%= link_to "more...", "/products/all", :id => "load-more", :remote => true %>

The server returns plain HTML (so that the link can be used on many different pages and is not bound to particular DOM IDs). We use the ajax:x events triggered by the Rails UJS drivers (here I'm using jQuery) to grab the server's response and insert it into the right element on the page:

<%= javascript_tag do %>
  $("#load-more").bind("ajax:complete", function(et, e){
    $("#products-list").html(e.responseText);
  });
<% end %>

If desired, we can also use the ajax:loading event to show a "spinner":

<%= javascript_tag do %>
  $("load-more").bind("ajax:loading", function(et, e){
    $(this).hide();
    $("#products-spinner").show();
  });
<% end %>

The Rails UJS drivers trigger four other events as well: ajax:success, ajax:failure, ajax:before, and ajax:after. See the driver included in your app (public/javascripts/rails.js) for more information.


in the js view /apps/views/product/index.js.erb you can write JS code such as the following

prototype:

$("products-list").update("<%= escape_javascript(render(@products))%>");

jquery:

$("products-list").html("<%= escape_javascript(render(@products))%>");

or

$("products-list").append("<%= escape_javascript(render(@products))%>");

and it will be executed when the request is successful


yes, you can apply the latter approach (write custom JS to get server response) by using link_to :remote.

you can also choose to get a json response, then update data on the page using JS. in any case, remember to render only the partial, not the entire page.

EDIT:

a sample code, this should make AJAX call when clicking something with id "more", then update a #product-list element in the page:

 $("#more").click(function() {
 // make a POST call and replace the content
    $.post(, function(data) {
      $("#products-list").html(data);
    });
  });

you don't need more code, and you can write some helper to generate this JS, instead of writing code in the view. btw this is yet UJS

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜