web-dev-qa-db-ja.com

AJAX Callback in Drupal 8を使用して、フォームテーブルに行を追加する方法

フォームテーブルに行を追加するボタンを実装しようとしています。ボタンのクリックごとに新しい行が追加されます。

私の問題は、AJAXコールバックでの変更が実際の$ formオブジェクトを変更していないようです:

最初のクリックで、行n°6が追加されますが、デフォルト値がないため、すでに問題となっています。次のclicsは効果がありません。コールバックの$ formパラメーターには6行目が含まれていません。

$ formを実際に変更する方法は何ですか?

これがビルドフォームです:

public function buildForm(array $form, FormStateInterface $form_state, Array $profile = NULL) {

$form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
);      

// table
$form['myTable'] = array(
'#type' => 'table',
'#header' => array(t('COL 1'), t('COL 2'), t('COL 3')),
'#prefix' => '<div id="my-table-wrapper">',
'#suffix' => '</div>',
);
// Build the table rows and columns.
for ($cpt = 0; $cpt <= 5; $cpt++) {
// Table row
$form['myTable'][$cpt] = $this->getTableLine($cpt);
}
$form['addRow'] = array(
    '#type' => 'button',
    '#value' => t('Add a row'),
    '#ajax' => array(
            'callback' =>  '::ajaxAddRow',
            'event' => 'click',
            'wrapper' => 'my-table-wrapper',
    ),
);

return $form;

}

ここで、行を埋めるために呼び出される関数:

function getTableLine($key) {
    $line = array();

    $line['col_1'] = array(
            '#type' => 'textfield',
            '#default_value' => 'col 1 - row ' . $key,
    );
    $line['col_2'] = array(
            '#type' => 'textfield',
            '#default_value' => 'col 2 - row ' . $key,
    );
    $line['col_3'] = array(
            '#type' => 'textfield',
            '#default_value' => 'col 3 - row ' . $key,
    );
    return $line;
}

そしてAjaxコールバック:

function ajaxAddRow($form, $form_state) {
    $cpt=0;
    for ($x = 0; $x <= 10 & $form['myTable'][$x]; $x++) {
        $cpt++;
    }

    // $cpt always return 6 - expected to increment
    // $form['myTable'][$cpt] is always empty

    $form['myTable'][$cpt] = $this->getTableLine($cpt);

    return $form['myTable'];

}
3
nicolas76

詳細と警告

フォームの変更は、フォームビルダー関数(この例では、ajax_example_autocheckboxes())でのみ行う必要があります。そうしないと、検証が失敗します。コールバック関数は、フォームやその他の状態を変更してはなりません。

リファレンス: https://www.drupal.org/docs/7/api/javascript-api/ajax-forms-in-drupal-7

D7向けですが、Ajaxの仕組みの概念は変わっていません。

ビッグアイデア

ここでの大きなアイデアは次のとおりです。

  • フォーム要素を操作すると、フォームが再構築されます(選択、送信など)。
  • フォームビルダー関数は、その入力($ form_state)に基づいて別の方法でビルドします
  • #ajax設定とコールバック関数は、新しく再構築されたフォームのすべてまたは一部を配信して、ページの一部を置換または拡張するように調整します。
2
4k4

これを管理するには、各クリックを検出し、フォームの非表示要素にクリックカウンターを設定します。

すべてはbuildFormで行われ、コールバック関数は単に更新するフォーム要素を返します。

public function buildForm(array $form, FormStateInterface $form_state, Array $profile = NULL) {


    $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Submit'),
    );      

    // table
    $form['myTable'] = array(
        '#type' => 'table',
        '#header' => array(t('COL 1'), t('COL 2'), t('COL 3')),
        '#prefix' => '<div id="my-table-wrapper">',
        '#suffix' => '</div>',
    );
    // Build the table rows and columns.
    for ($cpt = 0; $cpt <= 5; $cpt++) {
        // Table row
        $form['myTable'][$cpt] = $this->getTableLine($cpt);
    }


    // Build the extra lines
    $triggeringElement = $form_state->getTriggeringElement();
    $clickCounter = 0;
    // if a click occurs 
    if ($triggeringElement and $triggeringElement['#attributes']['id'] == 'add-row') {
        // click counter is incremented
        // $formstate and $form element are updated
        $clickCounter=$form_state->getValue('click_counter');
        $clickCounter++;
        $form_state->setValue('click_counter',$clickCounter);
        $form['click_counter'] = array('#type' => 'hidden', '#default_value' => 0, '#value' => $clickCounter);
    } else {
        $form['click_counter'] = array('#type' => 'hidden', '#default_value' => 0);
    }

    // Build the extra table rows and columns.
    for ($k=0 ; $k<$clickCounter ; $k++) {
        $form['myTable'][6+$k] = $this->getTableLine(6+$k);
    }


    $form['addRow'] = array(
            '#type' => 'button',
            '#value' => t('Add a row'),
            '#ajax' => array(
                    'callback' =>  '::ajaxAddRow',
                    'event' => 'click',
                    'wrapper' => 'my-table-wrapper',
            ),
            '#attributes' => array(
                    'id' =>  'add-row'
            ),
    );

    return $form;

}
0
nicolas76