ajaxコールバックが実行された後にフォームを再構築します


7

ボタンが付いたフォームがあり、これを押すとajaxリクエストを介してフォームの別の部分が再構築されます。

ボタンをクリックするとフォームが再構築され、フォームの値を保存してフォームの一部を返す私のajaxコールバックが呼び出されます。

問題は、値を保存するコールバックの前にフォームが再構築され、フォームの構築方法が変更されることです。

もう一度ajaxボタンをクリックすると、フォームがビルドされたときの前回のajaxリクエストの値と同じように正しく機能します。

フォームが再構築される前にコールバック関数を実行するにはどうすればよいですか?

function emtr_shift_plan_form($form, &$form_state) {

    ddl('build'); // log that this function is being called

    $form['save'] = array(
        '#type' => 'button',
        '#submit' => array('emtr_shift_plan_form_ajax_submit'),
        '#value' => 'Save',
        '#ajax' => array(
            'callback' => 'emtr_shift_plan_form_ajax_submit',
            'wrapper' => 'postions',
        ),
        '#id' => 'ajax-save-form-values',
    );

    $form['postions'] = array(
        '#type' => ' container',
        '#prefix' => '<div id="postions">',
        '#suffix' => '</div>',
    );

    // code here to populate the positions container

}

function emtr_shift_plan_form_ajax_submit($form, &$form_state) {

    ddl('ajax submit'); // log the ajax callback is being called

    $form_state['rebuild'] = TRUE; // As the form has already been rebuilt at this point what effect can this have?!?

    emtr_shift_plan_form_save($form, $form_state); // save the values

    // This is the point at which I want the form to be rebuilt

    return $form['positions'];

}

編集:

回避策として、を使用してajaxコールバックで2回目に手動でフォームを再構築できることを発見しましたが$form = drupal_rebuild_form('emtr_shift_plan_form', $form_state);、フォームを2回構築するのは非効率的です。Ajaxリクエストごとにフォームを2回ビルドするのではなく、これらのイベントの順序を入れ替えることはできますか?


2
送信機能で「保存」を行う必要があります。Ajaxコールバックは通常、フォーム要素を返すだけです。これで問題が解決する可能性もあります。
2pha、2014

回答:


2

私はこの質問が3歳であることを知っていますが、同様の問題を検索しているときに出くわしました。

これを機能させるには、アプローチを変更する必要があります。AJAXリクエストを送信するときの操作の順序は次のとおりです。

  1. AJAX送信コールバックが発生します。AJAX送信コールバックでは、データを保存する必要があります。$form_state変数にフラグを立てます。
  2. フォームが再構築されます。
  3. AJAXコールバックが発生します。

デモンストレーションのためにコードを少し修正しました。

// AJAX FLOW: 2. Form rebuild is fired.
function emtr_shift_plan_form($form, &$form_state) {

    ddl('build'); // log that this function is being called

    $form['save'] = array(
        '#type' => 'button',
        '#submit' => array('emtr_shift_plan_form_button_submit'),
        '#value' => 'Save',
        '#ajax' => array(
            'callback' => 'emtr_shift_plan_form_ajax',
            'wrapper' => 'postions',
        ),
        '#id' => 'ajax-save-form-values',
    );

    $form['postions'] = array(
        '#type' => ' container',
        '#prefix' => '<div id="postions">',
        '#suffix' => '</div>',
    );

    // code here to populate the positions container
    if (isset($form_state['saved_values'])) {
      // do stuff.
    }
}

// AJAX FLOW: 1. Button submit is fired.
function emtr_shift_plan_form_button_submit($form, &$form_state) {

  // log the ajax callback is being called
  ddl('ajax submit');

  // save the values. Make sure the data is stored somehow so your form can get at it.
  $form_state['saved_values'] = emtr_shift_plan_form_save($form, $form_state);

  // rebuild flag here will trigger emtr_shift_plan_form() to be run
  $form_state['rebuild'] = TRUE;
}

// AJAX FLOW: 3. Button callback is fired.
function emtr_shift_plan_form_ajax($form, &$form_state) {
    return $form['positions'];
}

それが誰かのためにいくつかの光を放つことを願っています。


2

このようにして、送信とコールバックを異なるものにして、それが役立つかどうかを確認できます。

$form['save'] = array(
    '#type' => 'button',
    '#submit' => array('emtr_shift_plan_form_ajax_submit'),
    '#value' => 'Save',
    '#ajax' => array(
        'callback' => 'emtr_shift_plan_form_ajax',
        'wrapper' => 'postions',
    ),
    '#id' => 'ajax-save-form-values',
);

function emtr_shift_plan_form_ajax($form, &$form_state){
  return $form['positions'];
}
function emtr_shift_plan_form_ajax_submit($form, &$form_state) {

    ddl('ajax submit'); // log the ajax callback is being called

    $form_state['rebuild'] = TRUE; // As the form has already been rebuilt at this point what effect can this have?!?

    emtr_shift_plan_form_save($form, $form_state); // save the values

    // This is the point at which I want the form to be rebuilt
}

ご提案ありがとうございますが、違いはないようです。そのボタンにajaxコールバックが定義されている場合、そのボタンは実際には送信ハンドラをまったく必要としません。
Felix Eve

これは確かに2phaコメントとともに正しい答えです。ajaxコールバック関数は出力を返すだけです。その他のアクションは、送信機能(要素がボタンまたは同等のものである場合)またはフォームを返す機能(または変更機能)で行う必要があります。したがって、問題は、コールバック後に再構築する方法ではなく、ajaxコールバック関数の前に計算を行う方法です。ここでの間違った仮定は、ajaxコールバック関数が送信関数であると考えることです。これは、出力を返す関数です:フォームフラグメントまたはAJAXコマンドです。
sanzante 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.