使用Rails 3的Ajax表单 - 最佳实践?

Chr*_*ngs 22 forms ajax ruby-on-rails unobtrusive-javascript

什么被认为是Ajax表单的Rails方式

直到今天我才认为我使用Rails表单+ jQuery UJS的方式是正确的方法,但是jQuery 1.7的升级'打破'到目前为止我的方式.

这该怎么做?

我想在表单中使用Ajax.ajax响应应该再次呈现表单(例如,发生错误时)或重定向到成功页面.(它应该可以做更多,比如显示模态,但我想保持这个例子简单).

1.使用EJS和$('#formid').html(...)

这就是我迄今为止所做的.我的ajax响应是一个ejs模板,它返回了javascript代码以再次呈现表单(有错误)或者取决于是否是错误将用户重定向到成功页面:

<% unless @success_submit %>
$('#form_wrapper').html('<%= escape_javacsript( render :partial => 'form' ) %>'); 
<% else %>
document.location = '/success_thank_you';
<% endif %>
Run Code Online (Sandbox Code Playgroud)

现在假设表单包含一个错误消息div like

<div class="error_message">BlaBla</div>
Run Code Online (Sandbox Code Playgroud)

为了添加一个很好的效果,我在ajax完成时绑定了一个通用的jQuery.live事件,突出显示了错误.

$('form').live('ajax:complete', function() {
   // do stuff like highlighting all error messages in that form
}); 
Run Code Online (Sandbox Code Playgroud)

这不再适用于jQuery1.7 + jquery-ujs(可能有很好的理由).所以我猜我做的方式不对.

2.使用上述方式但重复自己

而不是绑定ajax:complete事件我可以在EJS中执行"错误突出显示内容"

$('#form_wrapper').html('<%= escape_javascript( render :partial => 'form' ) %>');
$('#form_wrapper form .error_message').fadeIn();
Run Code Online (Sandbox Code Playgroud)

但这意味着我将不得不重复几乎每一个呈现形式的EJS的第二行.当然,我想保持干爽.

3. Ajax响应呈现纯html,ajax:完成事件处理显示

一个完全不同的解决方案是ajax响应只是渲染纯html和我的自定义ajax:完整的处理程序将负责显示表单.处理程序看起来像

$('form').live('ajax:success', function(ev, data, status, xhr) {
  $(this).html(data);
  // and e.g. highlight stuff
  $(this).children('.error_message').fadeIn();
});
Run Code Online (Sandbox Code Playgroud)

那会有用.但是现在如果我的服务器决定不再渲染表单(例如成功注册后),而是重定向到另一个URL或显示模态表单,我该怎么办?服务器可以响应类似的东西

<script>
   document.location = '/success.blabla/';
</script>
Run Code Online (Sandbox Code Playgroud)

但这是一个很好的解决方案吗?

4.自定义JSON协议

可能一个好的解决方案是使用版本3,但不是简单地用返回的html替换当前表单,我们可以创建一些自定义json协议.这样我们甚至可以让服务器响应类似的东西

  1. 首先显示模态(如'注册成功')
  2. 重定向到登录页面

ajax:success处理程序可以检查响应是否是纯html,在这种情况下,它将用html代码替换当前表单.但是如果响应是一个JSON数组,它将处理它,例如服务器响应

{ html: '<%= render :partial => 'something' %>', 
  show_modal:  '<%= render :partial => 'modal_template' %>',
  redirect_after_modal: '/login_page'
}
Run Code Online (Sandbox Code Playgroud)

ajax:success处理程序就像处理它一样

$('form').live('ajax:success', function(ev, data, status, xhr) {
   // try parsing json
   if (data.json['show_modal') { // show modal code.... }; 
   if (data.json['redirect']) { document.location=data.json['redirect']);...
});
Run Code Online (Sandbox Code Playgroud)

你是怎么做这件事的

显然,你有很多方法可以处理ajax表单.但是你是如何做到这一点的,以及Rails最佳做法是什么?

jan*_*eve 8

所以,我只能将你的问题归结为jquery,当然,它可以在jquery 1.6.4中运行,但不能在jquery 1.7中运行.

似乎如果替换DOM中的元素,然后在从原始元素创建的jquery对象上触发事件,1.6.4仍然会在元素原始位置触发事件并允许它向上传播DOM.但是,1.7不会触发元素(这更有意义).

我只是通过jquery 1.7 changelog进行了搜索,果然,这里有两张纠正了这种行为的票:995110489.

要回答你的什么问题,为实现这样的事情最好的做法,我会说,拿过来什么排列的活动消防控制.jQuery自动执行ajax响应中返回的JS,这意味着你无法控制何时发生这种情况.

修改代码最简单的方法是返回HTML部分本身,然后使用jquery与在返回的HTML替换形式ajax:completeajax:success/ ajax:error处理程序.通过这种方式,您可以确保按照您想要的确切顺序进行操作.

要了解如何完成此操作,请尝试阅读[我的文章]:

或者查看jquery-ujs wiki以获取这些链接等.