简体   繁体   English

Rails 4使用ajax,jquery,:remote => true和response_to渲染部分内容

[英]Rails 4 rendering a partial with ajax, jquery, :remote => true, and respond_to

It seems like rendering a page dynamically with AJAX in response to a submitted form is common. 用AJAX响应提交的表单动态呈现页面似乎很常见。 None of the other similar questions are focused around how to do this in a general way. 其他类似问题都没有集中于如何以一般方式进行此操作。

The best blog post I could find on the subject was here: http://www.gotealeaf.com/blog/the-detailed-guide-on-how-ajax-works-with-ruby-on-rails 我可以找到的关于该主题的最佳博客文章在这里: http : //www.gotealeaf.com/blog/the-detailed-guide-on-how-ajax-works-with-ruby-on-rails

The question: How do I code my rails application so that I can trigger a partial view to load via AJAX when I submit a form or click a link? 问题:如何编写Rails应用程序的代码,以便在提交表单或单击链接时可以触发通过AJAX加载的局部视图?

Several things must be present for this to work, including the :remote => true flag on the triggering element, the respond_to :js flag in the controller's class definition, the route, the partial view, and lastly the jquery to actually render a dynamic partial must be contained in a separate .html.js file. 要使此功能起作用,必须存在一些东西,包括触发元素上的:remote => true标志,控制器的类定义中的response_to:js标志,路线,局部视图,最后是jquery实际呈现动态效果。部分必须包含在单独的.html.js文件中。

Examples below are for a fictitious "render_partial_form" method of the "someajax" controller. 下面的示例针对“ someajax”控制器的虚拟“ render_partial_form”方法。


1) Add a :remote => true flag to the triggering element 1)在触发元素上添加:remote => true标志
put the :remote => true flag on the link or form tag in your .html.erb file (view) for the element that you want to trigger the AJAX call, like 将.remote => true标志放在您要触发AJAX调用的.html.erb文件(视图)中的链接或表单标记上(视图),例如

<%= form_tag("/someajax", method: 'post', :remote => true) do %>

with :remote => true, rails will not automatically switch views, which allows the JQuery to be run instead. 如果:remote => true,rails将不会自动切换视图,从而允许运行JQuery。 This can be used with a form_tag, a link_tag, or other types of tags. 可以与form_tag,link_tag或其他类型的标签一起使用。


2) Add "respond_to :html, :js" at the top of the controller 2)在控制器顶部添加“ respond_to:html,:js”

At the top of your controller's class definition, you must now specify that the controller can respond to javascript as well as html: 现在,在控制器的类定义的顶部,您必须指定控制器可以响应javascript和html:

class SomeajaxController < ApplicationController
   respond_to :html, :js

   ...

   def render_partial_form
      @array_from_controller = Array.new

      ...

   end
end

In this example, there's a variable being passed from the controller into the view: an array of select list options called @array_from_controller . 在此示例中,有一个变量从控制器传递到视图:一个名为@array_from_controller的选择列表选项的数组。


3) Route the http verb to your controller's method 3)将http动词路由到控制器的方法

Since I wanted a POSTed form to trigger the AJAX call, I routed the post verb for my controller to the render_partial_form view. 因为我想要一个POSTed表单来触发AJAX调用,所以我将控制器的post动词路由到了render_partial_form视图。

post 'someajax' => 'someajax#render_partial_form

The controller method defined by def render_partial_form matches with the name of the view, _render_partial_form.html.erb so there is no need to call a render action from the controller. 所限定的控制器方法def render_partial_form匹配与所述视图的名称, _render_partial_form.html.erb所以没有必要再调用来自控制器的渲染操作。


4) Create the partial view 4)创建局部视图
The partial view should have the same name as your controller method and begin with an underscore: _render_partial_form.html.erb 局部视图的名称应与控制器方法的名称相同,并以下划线开头: _render_partial_form.html.erb

<h3>Here is the partial form</h3>

<%= form_tag("/next_step", method: 'post') do %>
    <%= label_tag(:data, "Some options: ") %>
    <%= select_tag(:data, options_for_select(@array_from_controller.transpose[0].collect)) %>
    <%= submit_tag('Next') %>
<% end %>


5) Create the JQuery file 5)创建JQuery文件

JQuery statements trigger the form's rendering. jQuery语句触发表单的呈现。 Replace "render_partial_form" with the actual name of your controller method and partial view. 将“ render_partial_form”替换为控制器方法和部分视图的实际名称。 The slideDown effect is optional "eye candy". slideDown效果是可选的“眼睛糖果”。 Create a file with a .js.erb extension, and the same name as your controller: 创建一个扩展名为.js.erb的文件,其名称与您的控制器相同:

render_partial_form.js.erb

$('#render_partial_form').html("<%= escape_javascript (render partial: 'render_partial_form') %>");
$('#render_partial_form').slideDown(350);

You should use JS views (which have "js.erb" extension), something like "create.js.erb" for create controller action. 您应该使用JS视图(具有“ js.erb”扩展名),例如“ create.js.erb”之类的内容来创建控制器动作。 Then, add format.js to the respond_to do |format| ... end 然后,将format.js添加到format.jsrespond_to do |format| ... end respond_to do |format| ... end block. respond_to do |format| ... end块。 And add remote: true parameter to your form. 并在表单中添加remote:true参数。 Notice: js.erb should include Javascript code you need to be included, like: 注意:js.erb应该包含您需要包含的Javascript代码,例如:

$("tbody#items").append("<%= j render(partial: 'your_partial_path') %>")

For what it's worth (because I was tripping up on this in an app upgrade from Rails 2 to 3): you can also do it by adding an event handler that appends the returned HTML, like the old Rails 2 prototype library used to do. 物有所值(因为我在从Rails 2升级到Rails 3的应用程序中犯了此错误):您还可以通过添加附加返回的HTML的事件处理程序来做到这一点,就像以前的Rails 2原型库一样。

If, for instance, you're trying to take this (prepare for a runon sentence): 例如,如果您尝试采用此方法(准备runon句子):

form_remote_tag url: {...}, update: ...

Where the response is coming in as HTML and being appended automatically, and replace it with this: 响应以HTML形式出现并自动附加在其中,然后将其替换为:

form_tag {...}, remote: true

By adding an event handler to your application.js file that simply does the same thing, appending the content to a specific element, like this: 通过将一个事件处理程序添加到只做相同事情的application.js文件中,然后将内容附加到特定元素,如下所示:

$("#myform").on('ajax:success', function(e, data, status, xhr) {
  $("#container").append(data);
)};

Then... you may run into the same problem I did, which was that it never fires the ajax:success event! 然后...您可能会遇到我遇到的相同问题,那就是它永远不会触发ajax:success事件! The problem is that it's expecting JS or text in the response, but it's getting HTML. 问题在于,它期望在响应中包含JS或文本,但是却获取HTML。 The way to fix that is to tell it that the response will be HTML using an attribute on the form tag: 解决该问题的方法是使用form标记上的属性告诉它响应将是HTML:

form_tag {...}, remote: true, data: {type: :html}

Piece of cake! 小菜一碟!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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