如何指定 AJAX 响应?

发布于 2024-12-23 02:44:38 字数 2890 浏览 0 评论 0原文

我正在尝试 Rails3 / JQuery / unobtrusive javascript。我已经编写了一个玩具应用程序,可以在禁用 JS 的情况下执行我想要的所有操作,现在我想引入 javascript,这样服务器就不必在每次事务时刷新整个页面。

这是用于创建新玩具的非 JS 控制器/视图环境:

控制器

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>

(请原谅任何明显的复杂性,但 _list.html.erb 所做的只是列出所有现有玩具,如果 :target 引用新记录,则呈现_form 部分在列表的末尾。)

# ========== 
# 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 %>

ajaxification

我希望在启用 javascript 的版本中单击“新玩具”链接(在 index.html.erb 中)提交一个返回的 XMLHttpRequest 只有表单部分,它将就地呈现。该表格的发布将是标准远程 =>真实交易也是如此。

但我不知道如何让服务器仅返回表单。我将 ToysController 的新方法修改为:

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

... 并启用 :remote => index.html.erb 视图中 [New Toy] 链接中的 true 选项:

<%= link_to 'New Toy', new_toy_path, :class => 'new', :remote => true %>

现在我的代理 Web 调试器看到 GET /toys/new HTTP/1.1X-Requested-With: XMLHttpRequest (看起来正确),但响应是 HTTP/1.1 304 Not Modified

为什么它不渲染 _form.html.erb?

更新:避免“304 Not Modified”(非)响应

有两个问题 - @Robin 解决了主要问题。另一部分是我收到“304 Not Modified”响应——这在技术上是正确的,因为服务器已经发送了表单——但使调试变得困难。

因此,如果您尝试调试 javascript/ajax 代码,可以在控制器中调用“expires_now”,以强制服务器在调试时重新发送页面,如下所示:

def new
  @toy = Toy.new
  expires_now
  respond_to do |format|
    format.html ...
    format.js ....
  end
end

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:

controller

class ToysController < ApplicationController
...
def new
  @toys = Toy.all
  @toy = Toy.new
  respond_to do |format|
    format.html               # new.html.erb
  end
end

views

# ========== 
# 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 %>

ajaxification

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?

update: avoiding '304 Not Modified' (non-)responses

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

春夜浅 2024-12-30 02:44:38
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

$("#some_div").append("<%= escape_javascript(render "toys/form", :toy => @toy) %>")

如果您自己执行请求,则需要在 format.js 中呈现部分内容

$.ajax({
   success: function(data) {
       $("#some_div").append(data);
   }
})
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);
   }
})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文