web-dev-qa-db-ja.com

Ajaxを使用して選択した変更に新しいフォームフィールドを動的に追加する方法

モジュールで動的フォームを作成しようとしています。いくつかのオプションを含むselectタイプのフィールドが1つあります。1つのオプションを選択すると、新しいフィールドがフォームに動的に追加され、そこにオプションの別のリストが含まれます。ここで私がやろうとしていることは何も正しく動作していないようです

public function buildForm(array $form, FormStateInterface $form_state) {
    $this->controller = new Place_AdsController();
    $terms = $this->controller->content();

    $form['#attached']['library'][] = 'Place_Ads/general';
    $form['level1'] = array(
        '#type' => 'select',
        '#description' => 'Please select level one term',
        '#options' => $terms,
        '#attributes' => array(
            'class' => array(
                'mycategory'
            ),
        ),
        '#ajax' => array(
            // Function to call when event on form element triggered.
            'callback' => 'Drupal\Place_Ads\Form\Place_AdsForm::level1SelectedCallback',
            // Effect when replacing content. Options: 'none' (default), 'slide', 'fade'.
            'effect' => 'fade',
            // Javascript event to trigger Ajax. Currently for: 'onchange'.
            'event' => 'change',
            'progress' => array(
                // Graphic shown to indicate ajax. Options: 'throbber' (default), 'bar'.
                'type' => 'throbber',
                // Message to show along progress graphic. Default: 'Please wait...'.
                'message' => NULL,
            ),
        ),
    );
    return $form;
}
public function level1SelectedCallback(array &$form, FormStateInterface $form_state) {
    // Instantiate an AjaxResponse Object to return.
    $ajax_response = new AjaxResponse();
    if ($form_state->getValue('level1') != false) {
        $form['level2'] = array(
            '#type' => 'select',
            '#description' => 'Please select level two term',
            //'#options' => $terms,
            '#attributes' => array(
                'class' => array(
                    'mycategory'
                ),
            ),
        );
        $form_state->setRebuild(TRUE);
    }

    return $ajax_response;
}
4
Emad Karhely

Ajaxコールバックではなく、buildForm()でのみフォーム要素を構築します。 ajaxコールバックは、ajax応答を準備するためだけのものです。 ajaxコールバックが呼び出されたとき、buildForm()はすでに更新された$ formで実行されています。

あなたのajaxレスポンスは空です。それにajaxコマンドを追加していません。これを行う方法のajaxの例を参照してください。

しかし、あなたの場合、ajaxコールバックにコードは必要ありません。 $ formの変更された部分をdivコンテナーに返すだけで十分です。

このため、$ form_stateの条件が満たされた場合、buildForm()に空のコンテナを配置し、selectフォーム要素をajaxコールバックからbuildForm()に移動してコンテナに配置します。

$form['ajax_wrapper'] = [
  '#type' => 'container',
  '#attributes' => ['id' => 'ajax-wrapper'],
];

if ($form_state->getValue('level1') != false) {
        $form['ajax_wrapper']['level2'] = array(
            '#type' => 'select',
            '#description' => 'Please select level two term',
            //'#options' => $terms,
            '#attributes' => array(
                'class' => array(
                    'mycategory'
                ),
            ),
        );

そしてajaxコールバック:

public function ajaxCallback(array &$form, FormStateInterface $form_state) {
  return $form['ajax_wrapper'];

#ajaxを次のように変更します。

'#ajax' => [
  'callback' => '::ajaxCallback',
  'wrapper' => 'ajax-wrapper',
],
2
4k4