简体   繁体   中英

Easy AJAX HTML element replacement with Rails controllers?

I would love to be able to have an ERB partial like this:

<ul id='things-index'>
  <% @things.each do |t| %>
    <li><%= t.name %></li>
  <% end %>
</ul>

And be able to update it in the controller like so:

class ThingsController < ApplicationController
  def create
    @thing = Thing.new(params[:thing])
    @thing.save

    respond_to do |format|
      format.html
      format.js do
        @things = Thing.all
        page.replace('things-index')
      end
    end
  end
end

Meaning that JavaScript would be sent as a response without me having to explicity write a js.erb template like the following create.js.erb :

$('#things-index').replaceWith('<%= escape_javascript(render("things/index")) %>')

There may be something like this already, either built in to Rails or available as a gem, but if there is, I'm not aware of it.

I suppose ideally, it would re-render the 'index' action via JS and send the update to the browser, so it might look more like this:

respond_to do |format|
  format.html
  format.js do
    render 'index'
  end
end

And know to replace #things-index (or allow me to explicitly specify it).

Update

Whoops...Apparently there was page.replace_html when Prototype was part of Rails, but that functionality has been replaced by the .js.erb template method. That seems much less DRY to me (tons of near-identical js.erb templates), so if anyone has a solution, I'd appreciate it.

You can pass whatever you want to your js.erb, including what to replace, and with what.

$('<%= @id %>').replaceWith('<%= escape_javascript(render(@renderable)) %>')

Note Even in 2012 this wasn't really a recommended way of doing things like this. These days (early 2015) I'd say it's even less recommended given the great client-side technologies available.

Another solution would be to send back just the data, for the client to render as it choses:

respond_to do |format|
  format.html
  format.json do
   @things = Thing.all
   render :json => @things
  end
end

And on the client side:

function updateList(data){
  var $item,
      $list = $('#things-index');

  $list.find('li').remove();

  $.each(data, function(i, item){
    $item = $('<li />').text(item.name);
    $list.append($item);
  });  
}

$.getJSON('/my/route.json', function(data){
  updateList(data);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM