2014-03-26 70 views
1

我正在使用我的rails 4演示應用程序,並且我有一個按鈕用於在服務器端執行一些操作,然後返回json並顯示成功或失敗消息。rails 4 ajax event not triggering success

this問題類似,我看到響應返回了200代碼和期望的json有效載荷,但未觸發jQuery成功事件 - 使其更加混亂,似乎有些時斷時續 - 有時我會得到適當的操作(顯示一條閃光消息並刪除一個div),但大多數時候沒有任何反應。

下面是在視圖中按鈕:

<%= link_to 'Do Work', widget_path(:id => widget.id), id: widget.id, remote: true, method: :get %> 

這裏的控制器:

respond_to do |format| 
    if widget.save 
    // this json is returned properly 
    format.json { render json: { status: 'success', msg: 'Widget created.', :content_type => 'text/json', type: 'info', item: 'widget' } } 
    else 
    format.json { render json: @user.errors, :content_type => 'text/json', status: :unprocessable_entity } 
    end 
end 

application.js的JavaScript:

var fade_flash = function() { 
    $("#flash_success").delay(2000).fadeOut("slow"); 
    $("#flash_info").delay(2000).fadeOut("slow"); 
    $("#flash_warning").delay(2000).fadeOut("slow"); 
    $("#flash_danger").delay(2000).fadeOut("slow"); 
}; 
fade_flash(); 

var show_ajax_message = function(msg, type) { 
    $("#notice").html('<div id="flash_'+type+'" class="alert alert-dismissable alert-'+type+'"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>'+msg+'</div>'); 
    fade_flash(); 
}; 

這裏的的CoffeeScript在widget.js.coffee

$ -> 
    $("a[data-remote]").on "ajax:success", (e, data, status, xhr) -> 
    alert('got here') 
    console.dir(data) 
    if data.status == 'success' 
     show_ajax_message(data.msg, data.type) 
     if data.item == 'widget' 
      $('#widget_'+this.id).hide('slow') 
+1

我通常不使用這些事件,所以我不熟悉它。將事件綁定到「文檔」而不是鏈接時會發生什麼(如https://api.jquery.com/Ajax_Events/中所述? – jvnill

回答

0

Turbolinks

你的問題很可能是一個問題與Turbolinks

Turbolinks使得按照您的Web應用程序更快的鏈接。 而不是讓瀏覽器在每個頁面更改之間重新編譯JavaScript和CSS ,它使當前頁面實例保持活動狀態,並且 只替換頭部中的正文和標題。想想CGI VS 持久的過程

Turbolinks基本上加載使用Ajax網頁(留在原位<head>標籤),加載網頁速度更快...但也導致您的JS不火

問題是JS作品通過綁定加載到DOM元素。如果DOM元素不存在,他們不能被束縛,導致問題


修復

你需要解決這個問題是使用javascript delegation

這是通過結合事件的方式到一個「容器」元素(通常爲document)和,將分配給子元素。這工作,因爲document是始終存在的,因此JS將總是能夠火DOM元素是否存在在加載與否:

#app/assets/javascripts/application.js 
var fade_flash = function() { 
    $("#flash_success").delay(2000).fadeOut("slow"); 
    $("#flash_info").delay(2000).fadeOut("slow"); 
    $("#flash_warning").delay(2000).fadeOut("slow"); 
    $("#flash_danger").delay(2000).fadeOut("slow"); 
}; 

var show_ajax_message = function(msg, type) { 
    $("#notice").html('<div id="flash_'+type+'" class="alert alert-dismissable alert-'+type+'"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>'+msg+'</div>'); 
    fade_flash(); 
}; 

$(document).on("read page:load", fade_flash); 

#app/assets/javascripts/widgets.js.coffee 
$ -> 
    $(document).on "ajax:success", "a[data-remote]", (e, data, status, xhr) -> 
    // meaningless comment to get past edit limit-- added comma in line above 
    alert('got here') 
    console.dir(data) 
    if data.status == 'success' 
     show_ajax_message(data.msg, data.type) 
     if data.item == 'widget' 
      $('#widget_'+this.id).hide('slow')