几周以来,我一直在避免使用rails.js和remote: true
提供的Rails UJS“Ajax助手”。结果,我做了这样的事情:
// erb
<li>
<button type="button" class="btn btn-default btn-md">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span><%= tagging.tag.name %>
<%= hidden_field_tag :id, tagging.id %>
</button>
</li>
// js
remove_tag: function(){
$view.on('click','.cloud .glyphicon-remove', function(){
var id = $(this).next().val();
$.ajax({
type: "POST",
data: {id: id},
url: 'taggings/destroy',
beforeSend: function() {
$('.loading').show();
},
complete: function(){
$('.loading').hide();
},
success: function(resp){
alert( resp );
}
});
})
},
但是反复做这件事显然需要付出很多努力。所以我决定使用remote: true
和rails.js内置的不引人注目的功能更优雅:
<li>
<button type="button" class="btn btn-default btn-md">
<%= link_to tagging, remote: true, method: :delete, class: 'remove-tag' do %>
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
<% end %>
<%= tagging.tag.name %>
</button>
</li>
这转化为这个漂亮的代码:
<li>
<button type="button" class="btn btn-default btn-md">
<a class= "remove-tag" data-method="delete" data-remote="true" href="/taggings/1" rel="nofollow">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</a>
orange
</button>
</li>
现在我可以调用beforeSend并完成但是不会触发成功ajax事件。我遵循了this链接的建议。但是,'ajax:success'没有被称为:
remove_tag: function(){
$view.on('ajax:beforeSend', '.cloud .remove-tag', function(event, xhr, settings) {
$('.loading').show();
})
$view.on('ajax:complete', '.cloud .remove-tag', function(event, xhr, settings) {
$('.loading').hide();
})
$view.on('ajax:success', '.cloud .remove-tag', function(event, xhr, settings) {
alert("It was a success!")
})
},
如何调用'ajax:success'事件?
答案 0 :(得分:2)
我弄明白了这个问题。我的目标是消除不必要的使用:
$.ajax({
type: "POST",
data: $form.serialize(),
url: $form.attr('action'),
beforeSend: function() {
$('.loading').show();
},
complete: function(){
$('.loading').hide();
$form.closest('.modal').modal('hide')
},
success: function(resp){
console.log(resp);
}
});
通过在链接上使用remote: true
,Rails link_to
帮助器生成data-remote
属性,rails.js文件将为ajax请求添加事件监听器,因此不需要jquery $.ajax()
方法。
我没有意识到的是,ajax调用BY DEFAULT将dataType设置为&#39;脚本&#39;因此,HTTP请求标头Accept
标头设置为&#39; application / javascript&#39;。因此,响应中的内容类型将是:js
(application / javascript)。这要求您定义:action.js.erb
文件或传递块。但是如果你传递一个块,它将被一个被评估为JavaScript的块,而不是JSON或TEXT!因此,当我将JSON发送回浏览器时,它感到困惑。它期望评估javascript,而不是解析JSON,因此会发生解析错误。
$view.on('ajax:beforeSend', '.cloud .remove-tag', function(xhr, settings) {
$('.loading').show();
})
$view.on('ajax:complete', '.cloud .remove-tag', function(xhr, status) {
$('.loading').hide();
})
// this only triggered if you actually destroy record
$view.on('ajax:success', '.cloud .remove-tag', function(data, status, xhr) {
$('.loading').hide();
// JSON.parse not needed; status already parsed as json
var data_id = JSON.parse(status['data-id']);
$('.cloud').find("li[data-id='"+data_id['data-id']+"']").remove();
})
$view.on('ajax:error', '.cloud .remove-tag', function(xhr, status, error) {
console.log( error );
})
因此,ajax:error
被触发而不是ajax:success
。
当我更改链接以指定我想要json作为响应时,则ajax:success
被触发。
<%= link_to tagging, remote: true, method: :delete, class: 'remove-tag', :'data-type' => 'json' do %>
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
<% end %>
那么为什么我选择返回JSON而不只是使用format.js
并添加delete.js.erb
文件?因为这意味着我必须在js.erb文件中引用DOM id或类,因为我会丢失我创建的模块的上下文。通过将数据传递回事件监听器,我能够继续使用javascript函数创建的闭包。
答案 1 :(得分:1)
我不知道,你的$view
是什么,但下面的例子应该处理它。
$(document).ready(function() {
//form id
$('.remove-tag')
.bind('ajax:success', function(evt, data, status, xhr) {
//function called on status: 200 (for ex.)
console.log('success');
alert("It was a success!");
})
.bind("ajax:error", function(evt, xhr, status, error) {
//function called on status: 401 or 500 (for ex.)
console.log(xhr.responseText);
});
});
您还有第二个选项可以处理它,只需创建destroy.js.erb
文件。
console.log("Coupon | destroy.js.erb file");
$('nav').after("<div class='alert alert-danger'> Successfully Destroyed </div>");
$(".coupon_" + <%= @coupon.id %>).fadeOut(250, function(){
$(this).remove();
});