Cách kích hoạt Drupal.attachBehaviors sau khi Ajax thành công


10

Tôi có một mô-đun cập nhật một nút thông qua ajax khi nhấp vào một liên kết.

Liên kết là một chuyển đổi, nó sẽ cập nhật nút có giá trị 1 ở lần nhấp đầu tiên, sau đó với giá trị 0 ở lần nhấp tiếp theo, v.v. Giống như bật / tắt một cái gì đó.

Mã dưới đây hoạt động ở lần nhấp đầu tiên sau khi tải trang, nhưng không phải vào lần nhấp tiếp theo. Tôi tin rằng Drupal.attachBehaviors phải được gọi / kích hoạt sau mỗi lần nhấp, nhưng tôi không thể tìm ra cách để làm điều này.

  1. Mô-đun

    function mymodule_menu() {
      $items['mypath/%/%/ajax'] = array(
      'title' => 'My title',
      'page callback' => 'mymodule_ajax_callback',
      'page arguments' => array(1,2),
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK,
      );
    
      ...
    }
    
    function mymodule_ajax_callback($id, $status) {
      //Validation[...]
    
      //Node Update using $id as the nid and $status as the field value[...]
    
      // Define a new array to hold our AJAX commands.
      $ajax_commands = array();
    
      // Create a new AJAX command that replaces the #div.
      $replacedivid = '#status'.$id;
      $replacestring = '<div id="status'.$id.'"><a data-url="'.base_path().'mypath/'.$id.'/'.$new_status.'/ajax" title="This item is marked as '.$status_text.'" id="statuslink'.$id.'" class="midui">'.$status_text.'</a></div>';
    
    
      $ajax_commands[] = ajax_command_replace($replacedivid, $replacestring);
    
    
      return drupal_json_output($ajax_commands);
    }
  2. Javascript

    (function ($) {
      Drupal.behaviors.mymodule = {
        attach: function(context, settings) {
          var $uilink = $('.midui'); //find all links
    
          for (var i=0;i<$uilink.length;i++) { //Loop
            var $link = $('#' + $uilink[i].id);
            if (!$link.hasClass("middone")) {
    
              new Drupal.ajax('#' + $uilink[i].id, $link, {
                url: $link.attr('data-url'),
                effect: 'fade',
                settings: {},
                progress: {
                  type: 'throbber'
                },
                event: 'click tap'
              });
    
              $link.addClass("middone"); //add class when we're done
    
            }
          }
        }
      }
    })(jQuery);
  3. Những gì tôi đã cố gắng cho đến nay:

(a) Thêm một ajax_command_invoke(NULL, 'mymodule');vào mảng $ ajax_commands kết hợp với một $.fn.mymodulehàm

(b) Thêm $('body').ajaxSuccess(Drupal.attachBehaviors);vào javascript của tôi. ajaxComplete cũng đã thử. Đã thử nó trên tài liệu là tốt.

(c) Tạo một lệnh tùy chỉnh như chi tiết tại đây http://www.jaypan.com/tutorial/calling-feft-after-ajax-event-drupal-7

Lưu ý: Tôi biết rằng đó chỉ là vấn đề kích hoạt tệp đính kèm sau mỗi lần nhấp để 'ajaxify' html mới được chèn / sửa đổi. Nếu tôi nhấp vào liên kết và sau đó nhập Drupal.attachBehaviors () trong bảng điều khiển, liên kết sẽ được xử lý lại bằng javascript của tôi, bằng chứng là việc thêm lớp 'middone' và có thể được nhấp lại.

Lưu ý: Cũng đáng quan tâm, nếu tôi để $ajax_commandstrống và trả lại (mảng trống) ở cuối chức năng gọi lại, liên kết sẽ vẫn có thể nhấp vào lần nhấp đầu tiên và tiếp theo. Nó sẽ có chức năng mà tôi đang tìm kiếm (một chuyển đổi). Tuy nhiên, vì không có thay đổi nào được thực hiện đối với html sau mỗi lần nhấp, nên không có cách nào để người dùng biết liệu bật hay tắt.

Bât cư thông tin được cung câp nao cung được la sự suât hiện tuyệt vơi.

================================================== =====

Trả lời một phần:

Hàm thành công của Drupal ajax.js chỉ gắn lại các hành vi cho các biểu mẫu (tôi nghĩ sao?)

    if (this.form) {
      var settings = this.settings || Drupal.settings;
      Drupal.attachBehaviors(this.form, settings);
    }

vì vậy tôi quyết định hack tất cả chức năng thành công của các đối tượng ajax.

Javascript bây giờ trở thành

    (function ($) {
      Drupal.behaviors.mymodule = {
        attach: function(context, settings) {
          var $uilink = $('.midui'); //find all links

          for (var i=0;i<$uilink.length;i++) { //Loop
            var $link = $('#' + $uilink[i].id);
            if (!$link.hasClass("middone")) {

              myAjax = new Drupal.ajax('#' + $uilink[i].id, $link, {
                url: $link.attr('data-url'),
                effect: 'fade',
                settings: {},
                progress: {
                  type: 'throbber'
                },
                event: 'click tap'
              });

              myAjax.options.success = function (response, status) {
                //Trigger Attach Behaviors
                setTimeout(function(){Drupal.attachBehaviors($(myAjax.selector))}, 0);
                // Sanity check for browser support (object expected).
                // When using iFrame uploads, responses must be returned as a string.
                if (typeof response == 'string') {
                  response = $.parseJSON(response);
                }

                return myAjax.success(response, status);
              }

              $link.addClass("middone"); //add class when we're done

            }
          }
        }
      }
    })(jQuery);

Hàm thành công là một bản sao dán của mặc định từ ajax.js với một dòng được thêm vào cho các hành vi gắn lại. Vì một số lý do, Drupal.attachBehaviorsphải ở trong một bộ đếm thời gian. Tôi không thể tự mình làm điều đó vì một lý do mà tôi bỏ qua.

Tôi sẽ để câu hỏi này mở cho một vài người trong trường hợp ai đó có thể tìm ra giải pháp thanh lịch hơn và / hoặc giải thích sự kỳ lạ của bộ đếm thời gian.

Cảm ơn nhiều


Tại sao bạn muốn đính kèm hành vi nhiều lần? chúng được tự động chạy lại trên bất kỳ phần tử mới nào được tạo bằng AJAX, vậy tại sao nó không đủ?
Mołot

hành vi không được tự động gắn lại trong trường hợp của tôi. thx
JSL

Câu trả lời:


1

Có thể khó gắn các hành vi ajax vào nội dung được trả về từ chính yêu cầu ajax. Tuy nhiên, nó có thể.

Mặc dù đoạn mã hook_menu của bạn trông không đầy đủ, giả sử nó đúng (trả về $ item và chức năng đã bị đóng) - Trong trường hợp của bạn, bạn có thể chỉ cần điều chỉnh cuộc gọi lại chuyển phát thành 'ajax_deliver'

I E:

/**
 * Implements hook_menu
 */
function mymodule_menu() {

  $items['mypath/%/%/ajax'] = array(
    'title' => 'My title',
    'page callback' => 'mymodule_ajax_callback',
    'page arguments' => array(1,2),
    'access arguments' => array('access content'),
    'delivery callback' => 'ajax_deliver',
    'theme callback' => 'ajax_base_page_theme',
    'type' => MENU_CALLBACK,
  );

  return $items;

}

Cảm ơn lời đề nghị nhưng điều này cũng không hoạt động. Tôi sử dụng mã của bạn trong hook_menu và các hành vi không được tự động đính kèm lại.
JSL

1

Sau một số gỡ lỗi, tôi nhận ra vấn đề không nằm ở mã của tôi.

Vấn đề nằm ở một mô-đun khác, trong trường hợp của tôi là mô-đun hộp màu, là nguồn gốc của lỗi js trong chức năng hành vi của chính nó. Tôi tin rằng lỗi đã khiến quá trình hành vi đính kèm bị dừng lại và do đó, chức năng hành vi của chính tôi không được gắn lại. Các lỗi có thể được nhìn thấy trong giao diện điều khiển.

Lỗi hộp màu: trong 7.24

Uncaught TypeError: Cannot read property 'transition' of undefined colorbox_inline.js?

và trong 7,25

Uncaught TypeError: Cannot read property 'mobiledetect' of undefined

Giải pháp của tôi là vô hiệu hóa mô-đun hộp màu.

Rất cám ơn mọi người đã giúp đỡ.


1

Tôi không thể nhận xét câu trả lời đầu tiên , nhưng bạn có thể đặt thuộc tính cho hộp màu trong cài đặt. Ví dụ:

myAjax = new Drupal.ajax('#' + $uilink[i].id, $link, {
  url: $link.attr('data-url'),
  effect: 'fade',
  settings: {
    colorbox: {
      mobiledetect: false
    }
  },
  progress: {
    type: 'throbber'
  },
  event: 'click tap'
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.