【问题标题】:Ruby On Rails 3, form_tag remote on responding to Ajax requestRuby On Rails 3,form_tag 远程响应 Ajax 请求
【发布时间】:2011-04-30 13:00:12
【问题描述】:

感谢您阅读这篇文章。在过去的几天里,我一直被困在 RoR 的问题上。我在 index.html.erb 下有一个表单:

<head>
    <title>Ajax List Demo</title>
    <%= javascript_include_tag :defaults %>  
    <%= csrf_meta_tag %>  
</head>
<body>
  <h3>Add to list using Ajax</h3>

  <% form_tag :action => :list , :method=>:get, :remote=>true  do %>
    Enter the public url:<%= text_field_tag 'url' ,'', :size => 80 %>
    <%= submit_tag "Find" %>
  <% end %>

  <div id="my_list">
  </div>
</body>

在我的控制器中:

 def list
    puts "here!!!!"
    reader = Reader.new
    @profiles =  reader.processURL(params[:url]) #profileList = 
    respond_to do |format|
      #format.html { render :partial=>true, :locals => { :profiles => @profiles}}#{          render :partial=>'profiles/list',:layout => false, :locals => { :profiles => @profiles}} 

format.js {render :content_type => 'text/javascript', :locals => { :profiles => @profiles}}

# index.html.erb
      #   format.rss     render :partial=>'profiles/list',:layout => false, :locals => { :profiles => @profiles}
    end

还有一个用于远程 UJS 的 js 文件为 list.js.erb

$("#my_list").html("<%= escape_javascript(render(:partial => "list"))%>");

问题是我无法在 div 标签 my_list 中获得渲染部分 _list.html.erb 的结果。我得到一个空白页,406 错误。如果我取消注释控制器中的渲染 html 代码,我会在浏览器中获得部分返回。我有点卡住了,我想提交表单和结果以弹出 my_list div。我是 Rails 新手,所以如果我遗漏了一些明显的东西,请毫不犹豫地向我指出……我绝对愿意尝试。


改成这样:

<html>
    <head>
        <title>Ajax List Demo</title>
        <h1>Listing posts</h1>
           <%= javascript_include_tag 'jquery.js' %>  
    <%= csrf_meta_tag %>  
    </head>
    <body>
        <h3>Add to list using Ajax</h3>

        <% form_tag :action => :doit , :method=>:get, :remote=>true  do %>
        Enter the public url:<%= text_field_tag 'url' ,'', :size => 80 %>
        <%= submit_tag "Find" %>
        <% end %>

        <div id="my_list">
                   </div>

控制器:

def doit
    puts "here!!!!"
    reader = Reader.new
    @profiles =  reader.processURL(params[:url])
    respond_to do |format|
 #     format.html {render :partial=>true, :locals => { :profiles => @profiles}}#{    render :partial=>'profiles/list',:layout => false, :locals => { :profiles => @profiles}} 
      format.js #{render :content_type => 'text/javascript', :locals => { :profiles => @profiles}}
      # index.html.erb
      #   format.rss     render :partial=>'profiles/list',:layout => false, :locals => { :profiles => @profiles}
    end

JS _doit.js.erb $("#my_list").html(" "doit"))%>");

最后是部分:

_doit.html.erb.

但是我仍然收到 406 错误,我没有重复的 _doit js 或 erb。有什么突出的不正确吗?再次感谢!


另一个更新:

我认为表单渲染不正确:

这个渲染:

<% form_tag :action => :doit , :remote=>true, :id => 'myform' do %>
        Enter the public url:<%= text_field_tag 'url' ,'', :size => 80 %>
        <%= submit_tag "Find" %>
        <% end %>

这个:

<form accept-charset="UTF-8" action="/home/doit?id=myform&amp;remote=true" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="&#x2713;" />
<input name="authenticity_token" type="hidden" value="MLuau4hvfdGO6FrYCzE0c0JzwHhHKZqjmV49U673sK8=" />
</div>        Enter the public url:
<input id="url" name="url" size="80" type="text" value="" />

    <input name="commit" type="submit" value="Find" />



        <input name="commit" type="submit" value="Find" />

它在查询字符串中添加了我的远程标签和id,这不是错了吗?

Ok 终于知道表格需要用括号括起来了:

 <%= form_tag( { :action => 'doit' }, :multipart => true, :remote=>true, :id => 'myform' ) do %>

好的,今晚最后一次更新: 现在我进入日志:

2010 年 10 月 27 日星期三 22:40:55 -0400 开始为 127.0.0.1 发布“/home/doit” 这里!!!! 由 HomeController#doit as JS 处理 参数:{"commit"=>"Find", "url"=>"http://www.facebook.com/people/James-Stewart/653161299", "authenticity_token"=>"MLuau4hvf dGO6FrYCzE0c0JzwHhHKZqjmV49U673sK8=", "utf8"=>"Γ£ô"} 渲染 home/_doit.html.erb (4.0ms) 渲染 home/doit.js.erb (9.0ms) 在 807 毫秒内完成 200 次 OK(查看次数:40.0 毫秒 | ActiveRecord:0.0 毫秒)

我看到的是 JS,它说它渲染了我的 js/partial。但是我在 my_list div 上一无所获。我的 JS 文件:

$("#my_list").html("<%= escape_javascript(render(:partial => "doit"))%>");

我的 html.erb 表单文件现在有:

<script$('#myform').bind('ajax:success', function(evt, data, status, xhr){
    xhr.responseText;
  });></script>

就像表单什么都不做,这是一个好兆头,不再出现 406 错误。我知道这已经很接近了,如果有人能指出我需要在 js 中做什么,那就太好了,否则我会休息一下并尝试 tmrw。


好的,我认为它得到响应只是没有像您指出的那样呈现昨天史蒂夫的问题。

在 Firebug 上调试 JS 我看到了我想要在 div 中呈现的 html,为此:

http://localhost:3000/javascripts/prototype.js?1285674435/event/seq/1

这意味着我认为我现在收到了 JS 响应。

我在表单页面上有这个:

<script>$('#myform').bind('ajax:success', function(evt, data, status, xhr){
    $('#my_list').html(eval(xhr.responseText));
  });</script>

检查说它不知道 myform 是什么,但我在 Rails 代码中输入了 :id => 'myform'。


再次感谢,我在这里得到了很多帮助,我想与社区分享我最终是如何让它工作的。

doit 方法的 js 文件(定义需要一个更好的控制器动作名称)是 doit.js

代码最终是:

$("my_list").update("<%= escape_javascript(render(:partial => "doit"))%>");

由于某种原因,将其保留为 #my_list 在 Firefox 中找不到,我不得不使用 firebug 来最终解决这个问题。

显然这与下面建议的方式不同,我将把 js 脚本放回表单中并删除 .js.erb 文件,看看它是如何工作的。我想我只是在 format.js 响应中呈现部分内容?另外,每个人都在哪里找到有关编写 UJS 文件的信息?我对以 $ 开头的任何东西的语法一无所知。

再次感谢您的帮助,终于觉得我在学习轨道上取得了进步。

【问题讨论】:

    标签: ruby-on-rails ajax ruby-on-rails-3


    【解决方案1】:

    我在 Hacker News 上发布了这个答案,但我认为 Stack Overflow 社区也可能会受益 :-)

    在 Rails 3 中,javascript 驱动程序非常不干涉(即不引人注目)。您遇到的问题是您的应用程序正在向浏览器返回一个 javascript 字符串,但是页面中没有任何内容在页面上下文中执行该 javascript。

    rails.js ujs 驱动程序使用data-remote=true 绑定到表单和链接,:remote =&gt; true 正在这样做,以使他们远程提交请求,但这就是 Rails 魔法停止的地方。

    好消息是远程请求会触发一些您可以绑定到的事件,这使您可以访问服务器返回的数据(按以下顺序触发):

      ajax:before
      ajax:loading
      ajax:success
      ajax:complete
      ajax:failure
      ajax:after
    

    您需要将一个事件绑定到表单的ajax:success 事件。因此,如果您的表单的 id 为“myform”,您会希望在您的页面上出现这样的内容:

      $('#myform').bind('ajax:success', function(evt, data, status, xhr){
        eval(xhr.responseText);
      });
    

    xhr.responseText 是您的服务器返回的内容,因此这只是将其作为 javascript 执行。

    当然,也可以通过一些错误处理来绑定到失败事件。

    我通常什至不使用返回 javascript 的 action.js.erb 方法,我只是让我的控制器渲染 HTML 部分,然后我在页面中有这样的绑定:

      $('#myform').bind('ajax:success', function(evt, data, status, xhr){
        $('#target-div').html(xhr.responseText);
      });
    

    我实际上正在写一篇关于此的完整文章,但希望这足以让你继续前进。

    编辑:我完成了那篇文章,全面解释了 Rails 3 中的远程链接和表单。也许它会有所帮助:

    Rails 3 Remote Links and Forms: A Definitive Guide

    【讨论】:

    • 感谢 HN 和这里的回答。作为使用 javascript 的 .erb 用户,我依靠 $(document).ready(function ()... 和 sinatra 和 rails 来启动事件
    • Steve 感谢发布此内容,它帮助我了解 Ajax 和 Rails。我发布了更新,因为我认为从 rails 呈现的 html 似乎与我的预期不符。其他人得到这个?
    • 嗯,我再看一遍,xhr.responseText 只是一个字符串,这意味着将其放入您的函数中实际上不会执行它。尝试将“xhr.responseText”更改为“eval(xhr.responseText)”。我已经用它更新了我的示例。
    • 接近解决这个问题。我有萤火虫调试器显示我找回了 js。我会重新阅读你的建议,看看我是否能正确理解我的 js 脚本需要放在哪里。
    • 我终于完成了我提到的那篇文章,这可能会有所帮助。将其添加到帖子中(在底部)。
    【解决方案2】:

    如果您查看页面的呈现源,您应该注意到字段属性中的错误。

    正确的做法如下:

    <%= form_tag({:action => 'list'}, :remote => true %>
    

    注意大括号,非常重要!或者你可以这样做:

    <%= form_tag('list', :remote => true %>
    

    【讨论】:

      【解决方案3】:

      你有 2 个名为“_list”的部分吗?也许这会导致问题,您应该更具体一点:

      $("#my_list").html("<%= escape_javascript(render(:partial => "list.html.erb"))%>");
      


      我不确定这是否有帮助,但如果您在 IE 中使用,请注意 IE 发送的一些标头会影响您的控制器响应方式。因此,您可能使用 IE 发送 Ajax 请求,但您的 Rails 应用程序认为它只是一个普通的 html 请求。

      我不得不设置 jQuery 以首先删除当前的标头,然后只添加 javascript 标头:

      $.ajaxSetup({
      'beforeSend': function(xhr) {xhr.setRequestHeader("Accept",'');xhr.setRequestHeader("Accept", "text/javascript")}
      

      })

      【讨论】:

        【解决方案4】:

        使用list 作为控制器中的函数名可能是问题所在。 Rails 内部使用该名称。

        【讨论】:

        • 大家好,我发布了一个关注,将其从 list 更改为 doit,以确保它不是因为内部方法。 .js 渲染仍然没有返回任何内容,我收到 406 错误。
        【解决方案5】:

        Rails 5.1 引入了 rails-ujs,它改变了这些事件处理程序的参数。以下应该有效:

        $('#myform').bind('ajax:success', function(event) {
                const [_data, _status, xhr] = event.detail;
        
        });
        

        来源:https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers

        【讨论】:

          【解决方案6】:

          我知道这是一个老问题,但有人可以从中受益。

          我认为错误与此有关:

          JS _doit.js.erb $("#my_list").html(" "doit"))%>");

          最后是部分:

          _doit.html.erb.

          您正在创建一个_doit.js.erb 部分以响应控制器中的操作doit,但您需要的是一个名为doit.js.erb 的视图(不带下划线)。从概念上讲,您的操作中的 format.js 将响应具有相同名称且扩展名为 js.erb 的视图。

          【讨论】:

            猜你喜欢
            • 2012-10-01
            • 1970-01-01
            • 2012-01-16
            • 1970-01-01
            • 2012-10-16
            • 1970-01-01
            • 1970-01-01
            • 2012-06-06
            • 2012-05-24
            相关资源
            最近更新 更多