3

手短に:

Drupal フォームで AJAX コールバックが実行されるように、jQuery を介して外部イベントをトリガーしようとしています。これにより、いくつかの連鎖要素が再構築されます。一度機能しますが、Drupal の別の要素によってフォームが更新されるまで機能しません。

form_state は、最初の試行でトリガーされた要素として適切な要素を検出しますが、その後は form_state['buttons'] 配列で最初に使用可能なボタンにデフォルト設定されます。何かご意見は?

詳細に:

次のような複雑な Drupal フォームがあります。

A (ドロップダウン)

B (実際には B_key と B_literal、2 つのテキスト フィールド) C (ドロップダウン) D (ドロップダウン) E (ドロップダウン)

A が B を更新し、B が C を更新し、C が D を更新するなどです。B を除いて、これらはそれぞれドロップダウン要素です。各項目はキー => 値のペアであり、キーを使用して更新する要素のオプションを再構築します。したがって、C のキーが D のオプションに使用されるため、B のキーは C のオプションを更新します。

これらは完全に Drupal AJAX コールバックとして構築され、適切に動作します。ただし、B は選択ではなく、2 つの別個のテキスト フィールド、1 つはキー、1 つはリテラルです。これは、リストのサイズが大きすぎて select 要素を使用できないため、B の AJAX オートコンプリート ルックアップを実行できるようにするためです。

このルックアップを実行し、これら 2 つのフィールド (B_key と B_literal) にデータを入力する外部 jQuery スクリプトを作成しました。それらを入力したら、フィールドの 'aj​​ax' => 'event' => 'hs_changed' によって参照されるカスタム イベントをトリガーします。これは、jQuery('[name=b_literal]').trigger を使用して jQuery で手動でトリガーします。 (). これは私がこれを初めて実行したときに機能し、C が新しいオプション セットで再構築されます。

ただし、これが一度発生すると、再構築されなくなります。form_state を調べたところ、B の新しい値を選択すると、フォームの状態がボタン (form_state['buttons'] 配列の最初のボタン) がクリックされたと認識し、これが失敗することに気付きました。

ここで、A をリロードすると、通常は B の値があらかじめ設定されているため、すべての子フィールド (B、C、D、E) が適切に更新されます。これが発生したら、もう一度 B を手動で選択できます。もう一度試してみると失敗する前に、一度書かれたとおりに機能します。私のjQueryにはバインディングの問題がないことに注意してください。これは、Bのフィールドを見つけて値を更新できるためです。最初のトリガーの後に毎回失敗するカスタムイベントを手動でトリガーしています(drupalフィールドのajaxをトリガーします)。

コードは次のとおりです。

フォーム:

$form['a'] = array (
  '#type' => 'select',
  '#options' => $a_options,
  '#default_value' => $a_selected,
  '#required' => TRUE,
  '#prefix' => '<div id="a_wrapper">',
  '#suffix' => '</div>',
  '#ajax' => array(
    'callback' => 'a_ajax_callback',
    'method' => 'replace',
    'effect' => 'fade',
  ),
);

$form['b_key'] = array (
  '#type' => 'textfield',
  '#default_value' => $hierarchy['b_key'],
);

$form['b_literal'] = array (
  '#type' => 'textfield',
  '#default_value' => $hierarchy['b_literal'],
  '#size' => 32,
  '#required' => TRUE,
  '#ajax' => array(
    'callback' => 'b_ajax_callback',
    'method' => 'replace',
    'effect' => 'fade',
    'event' => 'hs_changed',
  ),
  '#prefix' => '<div id="b_wrapper">',
  '#suffix' => '</div>',
);

$form['c'] = array (
  '#type' => 'select',
  '#default_value' => $hierarchy['c'],
  '#empty_option' => '- Select -',
  '#options' => get_children_options_array($hierarchy['b_key'], TRUE),
  '#ajax' => array(
    'callback' => 'c_ajax_callback',
    'method' => 'replace',
    'effect' => 'fade',
  ),
  '#required' => TRUE,
  '#prefix' => '<div id="c_wrapper">',
  '#suffix' => '</div>',
);

//Assume D and E are identical to C

コールバック:

 function a_ajax_callback($form, &$form_state) {

   //Return the field to be rebuilt by the AJAX request  $commands = array();
   $commands[] = ajax_command_replace("#b_key_wrapper", render($form['b_key']));
   $commands[] = ajax_command_replace("#b_literal_wrapper", render($form['b_literal']));

   //We also unset a bunch of form_state['input'] values and such here

   return array('#type' => 'ajax', '#commands' => $commands);
 }

 //The b_ajax_callback and c_ajax_callback are pretty much identical

jQuery:

jQuery(document).on("focus", '[name=my_search]:not(.ui-autocomplete-input)', function() { 
  jQuery(this).autocomplete({
    source: function(req, res) {
      ch_search(req, res);
    },
    minLength: 3,
    select: function(event, ui) {
      ch_render_dropdowns(ui.item.id);
    }
  }); 
});

function ch_render_dropdowns(ch_node) {

  var token = jQuery('[name=ajax_token]').val();

  jQuery.ajax({
    url: '/ajax/myFunction/' + ch_node
    async: false,
    cache: false,
    data: {
      'token': token
    },
    success: function(data) {

      jQuery('#autoComplete_logic').html(data);
      jQuery('#autoComplete_logic').hide();

      // Once we have the initial results, fill in the d7 form fields
      // where we have values.
      var b_key = jQuery("#b_key").val();
      var b_name = jQuery("#b_literal").text();

      // Set our Drupal B Fields
      jQuery('[name=b_key]').val(b_key);
      jQuery('[name=b_literal]').val(b_name);

      //Trigger the refresh of all submenus in Drupal
      //This triggers the AJAX callback attached to the b_literal 
      //to rebuild c, d, and e.
      jQuery('[name=b]').trigger('hs_changed');
    }
  });
}

この問題の範囲外に多くのロジックがあるため、すべてを単純化しました。オートコンプリートは問題ではありません。b_literal フィールドにアタッチされた Drupal AJAX をアクティブ化して c、d、e のリフレッシュを引き起こすことは、Drupal のフォーム API を介して b、c、d、および e を内部的にリフレッシュするフィールド a をヒットしない限り、最初の時間以降は機能しません。 AJAX ロジック。

Form_state (初回は適切に実行):

[トリガー要素] => Array ( [#type] => textfield [#title] => B [#description] => [#default_value] => [#size] => 32 [#maxlength] => 255 [#required ] => 1 [#disabled] => [#ajax] => Array ( [callback] => b_ajax_callback [method] => replace [effect] => fade [event] => hs_changed )

        [#prefix] => <div id="b_literal_wrapper">
        [#suffix] => </div>
        [#input] => 1
        [#autocomplete_path] => 
        [#process] => Array
            (
                [0] => ajax_process_form
            )

        [#theme] => textfield
        [#theme_wrappers] => Array
            (
                [0] => form_element
            )

        [#pre_render] => Array
            (
                [0] => ctools_dependent_pre_render
            )

        [#defaults_loaded] => 1
        [#tree] => 
        [#parents] => Array
            (
                [0] => b
            )

        [#array_parents] => Array
            (
                [0] => b
            )

        [#weight] => 0.002
        [#processed] => 
        [#attributes] => Array
            (
            )

        [#title_display] => before
        [#id] => edit-b--4
        [#name] => b_literal
        [#value] => 
        [#needs_validation] => 1
    )

Form_state (2 回目以降は毎回不適切に実行されます):

[triggering_element] => Array
    (
        [#type] => submit
        [#value] => Submit
        [#weight] => 100
        [#attributes] => Array
            (
                [class] => Array
                    (
                        [0] => btn
                        [1] => btn-primary
                    )

            )

        [#after_build] => Array
            (
                [0] => _load_assets_b_select
            )

        [#input] => 1
        [#name] => op
        [#button_type] => submit
        [#executes_submit_callback] => 1
        [#limit_validation_errors] => 
        [#process] => Array
            (
                [0] => ajax_process_form
            )

        [#theme_wrappers] => Array
            (
                [0] => button
            )

        [#defaults_loaded] => 1
        [#tree] => 
        [#parents] => Array
            (
                [0] => submit
            )

        [#array_parents] => Array
            (
                [0] => submit
            )

        [#processed] => 
        [#required] => 
        [#title_display] => before
        [#id] => edit-submit--2
    )

[clicked_button] => Array
    (
        [#type] => submit
        [#value] => Submit
        [#suffix] => </div></section>
        [#weight] => 100
        [#attributes] => Array
            (
                [class] => Array
                    (
                        [0] => btn
                        [1] => btn-primary
                    )

            )

        [#after_build] => Array
            (
                [0] => _load_assets_b_select
            )

        [#input] => 1
        [#name] => op
        [#button_type] => submit
        [#executes_submit_callback] => 1
        [#limit_validation_errors] => 
        [#process] => Array
            (
                [0] => ajax_process_form
            )

        [#theme_wrappers] => Array
            (
                [0] => button
            )

        [#defaults_loaded] => 1
        [#tree] => 
        [#parents] => Array
            (
                [0] => submit
            )

        [#array_parents] => Array
            (
                [0] => submit
            )

        [#processed] => 
        [#required] => 
        [#title_display] => before
        [#id] => edit-submit--2
    )
4

1 に答える 1

2

jqueryでオートコンプリートを使用している場合に問題があると思います。その代わりに#autocomplete_path、Drupal 7 Form API で Given を使用するか、次のリンクを使用すると問題が解決する場合があります#autocomplete_path

于 2012-12-10T08:45:35.437 に答える