I'm dipping my toe into Rails3 / JQuery / unobtrusive javascript. I've written a toy app that does everything I want with JS disabled, now I want to introduce javascript so the server doesn't have to refresh the entire page on every transaction.
Here's the NON-JS Controller/View environment for creating a new Toy:
class ToysController < ApplicationController
...
def new
@toys = Toy.all
@toy = Toy.new
respond_to do |format|
format.html # new.html.erb
end
end
# ==========
# file: views/toys/index.html.erb
<%= render :partial => 'list', :locals => {:toys => @toys, :target => nil} %>
<%= link_to 'New Toy', new_toy_path, :class => 'new' %>
# ==========
# file: views/toys/new.html.erb
<%= render :partial => 'list', :locals => {:dj_monitors => @toys, :target => @toy} %>
# ==========
# file: views/toys/_list.html.erb
<div class='table-div'>
<div class='body-div'>
<% toys.each do |t| %>
<%= render :partial => 'toy', :locals => {:toy => t} %>
<% end %>
<% if target && target.new_record? %>
<%= render :partial => 'form', :locals => {:toy => target} %>
<% end %>
</div>
</div>
(Pardon any apparent complexity, but all _list.html.erb does is list all the existing toys, and if :target refers to a new record, renders the _form partial at the end of the list.)
# ==========
# file: views/toys/_form.html.erb
<%= form_for(toy) do |f| %>
<div class='column selected'><%= f.number_field :sku %></div>
<div class='column selected'><%= f.text_field :description %></div>
<div class='column selected'>
<%= link_to 'Cancel', toys_path %>
<%= f.submit %>
</div>
<% end %>
What I'd like in the javascript enabled version is that clicking on the 'new toy' link (in index.html.erb) submit an XMLHttpRequest that returns only the form partial , which would be rendered in-place. The posting of that form would be a standard remote => true transaction as well.
But I can't figure out how to get the server to return the form only. I modified ToysController's new method to:
def new
@toys = Toy.all
@toy = Toy.new
respond_to do |format|
format.html # new.html.erb
format.js { render :partial => 'form', :locals => {:toy => @toy} }
end
end
... and enabled the :remote => true option in the [New Toy] link in the index.html.erb view:
<%= link_to 'New Toy', new_toy_path, :class => 'new', :remote => true %>
Now my proxy web debugger sees GET /toys/new HTTP/1.1
with X-Requested-With: XMLHttpRequest
(that looks right), but the response is HTTP/1.1 304 Not Modified
Why isn't it rendering _form.html.erb?
There were two issues -- @Robin solved the main problem. The other part was that I was getting a "304 Not Modified" response -- it was technically correct, since the server had already sent the form -- but made debugging difficult.
So if you're trying to debug javascript / ajax code, it can help to stick a call to 'expires_now' in your controller to force the server to re-send the page while you're debugging, like this:
def new
@toy = Toy.new
expires_now
respond_to do |format|
format.html ...
format.js ....
end
end
def new
@toy = Toy.new
respond_to do |format|
format.html { @toys = Toy.all } #you only need to get all toys in this case (and you should add pagination)
format.js
end
end
in new.js.erb
$("#some_div").append("<%= escape_javascript(render "toys/form", :toy => @toy) %>")
You would need to render the partial in the format.js
if you did the request yourself:
$.ajax({
success: function(data) {
$("#some_div").append(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.