Ruby On Rails 3,form_tag远程响应Ajax请求

时间:2010-10-26 03:03:50

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

感谢阅读这篇文章。过去几天我一直坚持使用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。我是新手,所以如果我错过了一些明显的东西,请毫不犹豫地向我指出......我绝对愿意尝试。


将其更改为:

<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(“&lt;%= escape_javascript(render(:partial =&gt;”doit“))%&gt;”);

最后是部分:

_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添加到查询字符串中,这不是错误的吗?

好的,最后得到一个线索形式需要括号:

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

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

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

我看作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。


好的,我认为它的回复只是没有像你指出的那样呈现,这将是昨天Steve的问题。

在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是什么,但我把:id =&gt; Rails代码中的'myform'。


再次感谢,我在这里得到了很多帮助,我想分享一下我最终如何回到社区。

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

代码最终是:

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

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

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

再次感谢您的帮助,最后感觉我在学习轨道方面取得了进展。

6 个答案:

答案 0 :(得分:26)

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

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

rails.js ujs驱动程序绑定到data-remote=true的表单和链接,这是:remote => 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执行。

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

我通常甚至不使用action.js.erb方法返回javascript,我只是让我的控制器渲染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

答案 1 :(得分:6)

如果查看页面的渲染源,您应该注意到fields属性中的错误。

正确的方法如下:

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

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

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

答案 2 :(得分:2)

你有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")}

})

答案 3 :(得分:1)

在控制器中使用list作为功能名称可能是个问题。该名称由Rails内部使用。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

我认为错误与此有关:

JS _doit.js.erb $(“#my_list”)。html(“ <​​%= escape_javascript(render(:partial =>” doit“))%>”))

最后是部分:

_doit.html.erb。

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