web-dev-qa-db-ja.com

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

ボタンが付いたフォームがあり、これを押すと、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'];

}
_

編集:

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

7
Felix Eve

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

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

  1. AJAX送信コールバックが発生します。 AJAX submitコールバックでは、データを保存する必要があります。$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
Scott Joudry

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

$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
}
2
Ali Nouman