2014-03-29 66 views
3

我想知道在Rails 4中處理ajax調用的正確方式是什麼(使用remote:true選項時),問題是我想在處理過程中使用所有經典步驟,例如成功,錯誤,beforeSend和完成。在Rails 4中處理AJAX調用(成功,錯誤,beforeSend,完成)

所以我們可以說我有這個按鈕,它加載模態窗口,在它的一些AJAX:

視圖(產品/指數):

<%= link_to('Order this', new_order_path(product: product), remote: true) %> 

orders_controller:

def new 
     @order = Order.new 
     @product = Product.find(params[:product]) 

     respond_to do |format| 
      format.html 
      format.js 
     end 
     end 

new.js.erb:

(function(){ 
    var $modalWindow = ... 
    // some code that loads the modal window and closes it 

    $modalWindow.html("<%= j render('form') %>"); // puts the needed product form 
                into my modal window 
}()); 

這工作正常,但在此代碼前/後/成功/錯誤去哪裏?

而接下來,在「訂單產品」按鈕被點擊時,我有這在我的訂單控制器:

def create 
    @product = Product.find_by(params[:id]) 
    @order = current_office.orders.build(order_params) 

    respond_to do |format| 
     if @order.save 

     format.html { 
      flash[:success] = 'Order created' 
      redirect_to products_url 
     } 
     format.js 
     else 
     render :new 
     format.html { render :new } 
     format.js { render :js=>'alert("ajax error");' } 
     end 
    end 
    end 

同樣,點擊按鈕「創建」的時候,我怎麼去處理?我的create.js.erb只關閉模式窗口,但是我希望它完全處理請求,在發送之前顯示預加載器,然後顯示成功/錯誤,然後顯示。

希望不要太亂!

回答

1

這段代碼的前/後/成功/錯誤在哪裏?

ajax events沒有在該代碼屬於 - 因爲他們不能被綁定到原來的DOM元素。你需要把它們放在始發JS - 因爲只有這樣,是的元素被綁定到其發送請求的DOM元素:

#app/assets/javascripts/application.js 
$(document).on("ajax:success", "#element", function() { 
    //do something 
}); 

這裏是一個很好的資源爲你:rails3 rails.js and jquery catching success and failure of ajax requests


後端

如果你要處理的後端處理代碼,你需要使用某種驗證以確定應該發生的事情:

#app/controllers/orders_controller.rb 
def new 
    @order = Order.new 
    @product = Product.find(params[:product]) 

    respond_to do |format| 
     format.html 
     format.js { @state = "success" } 
    end 
    end 

#app/views/orders/new.js.erb 
(function(){ 
    <% if @state && @state == "success" %> 
     var $modalWindow = ... 
      $modalWindow.html("<%= j render('form') %>"); 
    <% else %> 
     alert ("not successful"); 
    <% end %> 
}()); 

前端

如果你想處理的前端Ajax請求,你最好做這樣的事情:

#app/assets/javascripts/application.js 
$(document).on("ajax:success", "#element", function(){ 
    //do something 
}); 

插件

我沒有任何文檔,這個尚未:

(function($){   

    $.fn.leanModal = function(options) { 

     //Defaults 
     var defaults = { 
      overlay: 0.5, 
      overlay_color: "#000", 
      closeButton: null, 
      delay: null, 
      drag: ".modal_title", 
      removeModal: null, 
      autoLoad: null, 
      ajax: false 
     }; 

     //Definitions 
     var xhr; 
     var plugin = this; 
     var options = $.extend(defaults, options); 

     //Init 
     plugin.init = function() { 

      if(options.autoLoad){ 
       $.extend(options, {modal_id: $(this)}); 
       create(); 
      }else{ 
       return this.each(function() { 
        $(this).click(function(e) { 
         e.preventDefault(); 
         var href = $(this).attr("href"); 
         var image = CheckImg(href); 

         var random = Math.floor(Math.random()*90000) + 10000; 
         var extras = (options.ajax || image) ? {modal_id: "#modal_" + random, ajax: href.replace(/\/$/, '')} : {modal_id: href}; 

         $.extend(options, extras); 
         create(); 
        }); 
       }); 
      } 
     } 

     ////////////////// 
     // Actions // 
     ////////////////// 

     //Build 
     var create = function() { 
      if(options.ajax){ 

       //Loading 
       load(); 

       //Image 
       switch (true) { 
        case CheckImg(options.ajax): 
         append("img", options.modal_id.substring(1), options.ajax); 
         show(); 
         break; 
        default: 
         fetch(options.ajax, function(data){ 
          append("modal", options.modal_id.substring(1), options.ajax, data); 
          show(); 
         }, function(xhr, text_status, error_thrown){ 
          load(); 
          alert("Sorry, there was an error!"); 
         }); 
         break; 
       } 

      }else{ 
       show(); 
      } 
     } 

     //Ajax 
     var fetch = function(link, success, error) { 
      xhr = 
      $.ajax({ 
       url: link, 
       success: function(data) { success(data); }, 
       error: function(data) { error(data); } 
      }); 
     } 

     //Overlay 
     var olay = function(modal_id, removeModal, closeButton, ajax) { 
      var overlay = document.createElement("div"); 
       overlay.setAttribute("id", "lean_overlay"); 

      document.body.appendChild(overlay); 
      overlay.onclick = function() { close(modal_id, removeModal, $(closeButton), ajax); return false; }; 
     } 

     //Show 
     var show = function() { 

      /* Vars */ 
      var id   = options.modal_id 
      var removeModal = options.removeModal 
      var closeButton = options.closeButton 
      var drag  = options.drag 
      var ajax  = options.ajax 
      var opacity  = options.overlay 

      /* Overlay */ 
      olay(id, removeModal, closeButton, ajax); 

      /* Elements */ 
      var modal  = $(id); 
      var overlay  = $("#lean_overlay"); 

      /* Display */ 
      var disp  = "test"; 

      /* Options */ 
      if (closeButton) { 
       $(closeButton).css("z-index", "900"); 
       $(closeButton).on("click", function (e) { 
        e.preventDefault(); 
        close(id, removeModal, $(closeButton)); 
        return false; 
       }); 
      } 

      /* Load */ 
      if (ajax) { 
       modal.waitUntilExists(function() { 
        load(); 
        display($("#lean_overlay"), options.overlay_color, $(options.modal_id), options.overlay, options.drag); 
       }) 
      } else { display($("#lean_overlay"), options.overlay_color, $(options.modal_id), options.modal, options.overlay, options.drag); } 
     } 

     //Close 
     var close = function(modal, removeModal, closeButton, ajax) { 

      /* Ajax */ 
      if(ajax){ 
       if (xhr) { xhr.abort(); } 
       load(true); 
      } 

      /* Overlay */ 
      $("#lean_overlay").fadeOut(150, function(){ 
       $(this).remove(); 
       if(closeButton) { 
        closeButton.off("click"); 
        closeButton.removeAttr('style'); 
       } 
      }); 

      /* Modal */ 
      $(modal).fadeOut(150, function(){ 
       if (removeModal) { 
        $(this).remove(); 
       } 
      }); 

     } 

     //Go 
     plugin.init(); 
    }; 


    ////////////////// 
    // Dependencies // 
    ////////////////// 

    //Image? 
    var CheckImg = function(url) { if(url) { return(url.match(/\.(jpeg|jpg|gif|png)/) != null); }} 

    //Create 
    var append  = function(type, id, src, data) { 

     //Definitions 
     var style = element = type; 

     if (type == "modal") { 
      var style = "ajax"; 
      var element = "div"; 
     } 

     //Element 
     var el = document.createElement(element); 
      el.setAttribute("id", id); 
      el.setAttribute("src", src); 
      el.className = 'modal ' + style; 

     //Ajax 
     if (data) { el.innerHTML = data; } 

     //Append 
     document.body.appendChild(el); 
    } 

    //Show 
    var display = function(overlay, overlay_color, modal, opacity, drag) { 

     /* Styling */ 
     overlay.css({ 
      "display": "block", 
      "background": overlay_color, 
      opacity: 0 
     }); 
     modal.css({ 
      "display": "block", 
      "position": "fixed", 
      "opacity": 0, 
      "z-index": 10200, 
      "left": 0, 
      "right": 0, 
      "top": 0, 
      "bottom": 0, 
      "margin": "auto" 
     }); 

     /* Init */ 
     overlay.fadeTo(150, opacity); 
     modal.fadeTo(200, 1); 
     if(drag.length > 0) { modal.draggable({ handle: drag }); } 

    } 

    //Ajax Load 
    var load = function(close) { 
     if (close) { $(document).ajax_load({close: true}); } else { $(document).ajax_load(); } 
    } 

})(jQuery); 

使用

#app/assets/javascripts/application.js 
var load = function() { 
    $('a[rel*=LeanModal]').leanModal({ 
     overlay: 0.9, 
     removeModal: true, 
     closeButton: ".title .close" 
     ajax: true, 
     drag: ".title" 
    }); 
} 
$(document).on("ready page:load", load); 

#app/assets/sytlesheets/application.css.sass 
/Overlay 
#lean_overlay 
position: fixed 
z-index: 1500 
top: 0px 
left: 0px 
height: 100% 
width: 100% 
display: none 

&:hover 
    cursor: pointer 

// Modal 
.modal 
    //styling here 


#app/views/application/index.html.erb 
<%= link_to "test_ajax", ajax_path, rel: "LeanModal" %> 

#app/controllers/application_controller.rb 
layout Proc.new {|controller| controller.request.xhr? ? false : "application" } 
+0

這是一個偉大的回答,非常感謝你。 $(document).on(「ajax:success」)存在的一個問題是,如果我執行多種不同的ajax操作,我將始終對我的應用程序有相同的反應,因爲它們都是相同的? –

+1

謝謝!RE: '$(document)' - 不是如果你委託給發起請求的元素 - https://learn.jquery.com/events/event-delegation/ –

+0

謝謝。現在我想混合ruby代碼與JS可能是一個不好的做法,尤其是在未來,我可能只是去用Javascript和經典的方式做的東西,通過良好的$ .ajax –

相關問題