Ajaxの成功後にDrupal.attachBehaviorsをトリガーする方法


10

リンクをクリックしたときにajaxを介してノードを更新するモジュールがあります。

リンクはトグルです。最初のクリックでノードを値1で更新し、その後のクリックで値0でノードを更新する必要があります。

以下のコードは、ページの読み込み後の最初のクリックでは機能しますが、その後のクリックでは機能しません。クリックするたびにDrupal.attachBehaviorsを呼び出し/トリガーする必要があると思いますが、これを行う方法がわかりません。

  1. モジュール

    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. これまでに試したこと:

(a)関数とajax_command_invoke(NULL, 'mymodule');組み合わせた$ ajax_commands配列にを追加し$.fn.mymoduleます

(b)$('body').ajaxSuccess(Drupal.attachBehaviors);JavaScriptに追加します。ajaxCompleteも試しました。ドキュメントでも試してみました。

(c)ここで詳しく説明されているようにカスタムコマンドを作成しますhttp://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7

注:挿入または変更される新しいhtmlを「ajaxify」するためにクリックするたびにattachBehaviorsをトリガーするだけの問題であることはわかっています。リンクをクリックして、コンソールにDrupal.attachBehaviors()と入力すると、「middone」クラスが追加されたことからわかるように、リンクはJavaScriptによって再び処理され、再度クリックできるようになります。

注:また興味深いことに、$ajax_commandsコールバック関数の最後で空のままにしてそれ(空の配列)を返すと、1回目以降のクリックでリンクがクリック可能なままになります。私が探している機能(トグル)があります。ただし、クリックするたびにhtmlは変更されないため、ユーザーがトグルがオンかオフかを知る方法はありません。

どんなポインタでも大歓迎です。

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

部分的な答え:

Drupalのajax.js成功関数は、フォームの動作のみを再アタッチします(私はそう思いますか?)

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

そこで、すべてのajaxオブジェクトの成功関数をハックすることにしました。

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")) {

              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);

成功関数は、動作を再接続するための行が追加されたajax.jsからのデフォルトのコピーペーストです。何らかの理由Drupal.attachBehaviorsで、タイマー内にある必要があります。私が無視する理由のために、それだけでそれを手に入れることはできません。

誰かがよりエレガントな解決策を見つけたり、タイマーの奇妙さを説明したりできる場合に備えて、この質問はほとんど公開しません。

どうもありがとう


なぜビヘイビアを何度もアタッチしたいのですか?AJAXを使用して作成された新しい要素で自動的に再実行されるので、なぜそれで十分ではないのですか?
Mołot

私の場合、動作は自動的に再接続されません。thx
JSL

回答:


1

ajaxリクエスト自体から返されるコンテンツにajaxビヘイビアーをアタッチするのは難しい場合があります。ただし、可能です。

あなたのhook_menuコードスニペットは、それが正しいと仮定して不完全に見えますが($ itemsを返し、関数は閉じています)-あなたの場合、配信コールバックを「ajax_deliver」に調整する必要があるだけかもしれません

つまり:

/**
 * 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;

}

提案ありがとうございますが、これも機能しません。私はあなたのコードをhook_menuで使用し、ビヘイビアーが自動的に再接続されません。
JSL

1

いくつかのデバッグの後、問題は自分のコードにあるのではないことに気付きました。

問題は別のモジュール(私の場合はcolorboxモジュール)にありました。これは、独自の動作関数のjsエラーの原因でした。エラーが原因で動作のアタッチプロセスが停止したため、自分の動作関数は再アタッチされませんでした。エラーはコンソールで確認できます。

カラーボックスエラー:7.24

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

そして7.25

Uncaught TypeError: Cannot read property 'mobiledetect' of undefined

私の解決策は、カラーボックスモジュールを無効にすることでした。

助けてくれたすべての人に感謝します。


1

最初の回答にはコメントできませんが、設定でカラーボックスのプロパティを設定できます。例えば:

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'
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.