Rails这个超级强大的网站构建器为用户界面变更和交互提供了ajax操作的能力,据我所知在Rails中使用ajax有两种方法,下面为大家一一道来 ;)
一.在$(document).ready中注册hook,伺机而动
我们可以为html中某个元素注册回调钩子,比如在select中的选项发生改变的时候:
<%= select_tag("department",options_from_collection_for_select(@departments,"id","name"),include_blank:false,:'data-remote'=>'true',:'data-url'=>url_for(controller:'static_pages',action:'dep_changed'),:'data-type'=>'json') %>
上面代码中首先开启了data-remote确保触发远程调用,注意最后一个data-type的类型为json,这决定了控制器中的响应类型:
def dep_changed
log(params)
dep = Department.find(params[:department])
render :json=>dep.offices.map {|office| [office.id,office.name]}
end
最后需要为#department注册hook:
$(document).ready(function() {
// #first_select is the id of our first select Box,if the ajax request has been successful,
// an ajax:success event is triggered.
$('#department').on('ajax:success',null,function(evt,data,status,xhr) {
//do some staff...
});
});
});
那么我们在这种情况下如何调试呢?以MacOS的Safari为例,打开对应html页面,选择开发菜单->资源->脚本->application.js:
你可以在其中任意下断点,很方便不是吗!?
二.以Javascript方式响应
第二种方式不用注册回调,不用修改全局的application.js文件,你只需要为特定的动作创建js.erb脚本即可,首先将select中的data-type项删掉,这样默认是以js方式响应.
修改对应Action:
def dep_changed
log(params)
dep = Department.find(params[:department])
@offices = dep.offices
respond_to do |format|
format.js
end
end
创建与action同名的js.erb文件dep_changed.js.erb:
(function() {
var office_select = $('#office');
office_select.empty();
var opt = null;
<% @offices.each do |office| %>
opt = $('<option/>');
opt.attr('value',<%=office.id%>);
opt.text('<%=office.name%>');
opt.appendTo(office_select);
<% end %>
}).call(this);
不过这种方法无法下断点调试,但是你可以看到执行后的代码,还是以Safari为例,在打开了开发界面后,选择资源->XHR:
在每次触发JavaScript脚本时,都会生成新的响应js代码,如上图所示.
值得注意的是以第二种ajax方式操作时,即使删除了html元素的data-type项,但如果你在application.js中为该元素设定了hook,则任然会触发,只不过此时会出现错误,提示data对象非法,因为你没有接收到json数据.如果你一定要同时使用两种方法,那么你必须预先判断data是否有效.