AJAX呼び出し後にフォームを再構築する方法


12

私は、ユーザーがajax呼び出しを使用してドロップダウンボックスに基づいて多数のフィールドを動的に選択できるようにしていますが、後でフォームを再構築するためにajax呼び出しを取得できないようです。

<?php
class AJAXexample extends BlockBase {
    public function blockForm($form, FormStateInterface $form_state) {
        if (empty($form_state->getValue('number'))) {
            $form_state->setValue('number', 3);
        } 
        $form['columnNum'] = [
            '#title'   => t('Number of Columns'),
            '#type'    => 'select',
            '#options' => [
                1         => '1',
                2         => '2',
                3         => '3',
                4         => '4',
            ],
            '#default_value' => $this->configuration['columnNum'],
            '#empty_option'  => t('-select-'),
            '#ajax'          => [
                'callback'      => [$this, 'columnCallback'],
            ],
        ];
        for ($i = 0; $i < $form_state->getValue('number'); $i += 1) {
            $form['column'][$i] = [
                $i => [
                    '#type'       => 'details',
                    '#title'      => t('Column '.$numTitle),
                    '#open'       => FALSE,
                    'columnTitle' => [
                        '#type'      => 'textfield',
                        '#title'     => t('Column Title'),
                        '#value'     => $config[0]['columnTitle'],
                    ],  
                ],
            ];  
        return $form;
    }

    public function columnCallback(array &$form, FormStateInterface $form_state) {
        $form_state->setValue('number', 10);
        $form_state->setRebuild(true);
        return $form;
    }
}

テキストフィールドの数は、form_state変数「number」に基づいています。コールバックcolumnCallbackはform_state変数を10に変更し、「columnNum」フォームフィールドが変更されると起動されます。ただし、$ form_state-> setRebuild();であっても、フォームは新しいフィールド数で再構築されません。と呼ばれます。ajax呼び出し後にフォームを再構築する方法はありますか?

注:実際のajax呼び出し内でフォームの項目を置換または追加するなどの手法を既に試しましたが、その場合、置換されたフィールドへの入力は$ form_stateに渡されません。

更新:4k4のソリューションを試行した後、エラーが表示されます

Recoverable fatal error: Argument 1 passed to Drupal\Core\Render\MainContent\AjaxRenderer::renderResponse() must be of the type array, null given, called in /Library/WebServer/Documents/aaep/web/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php on line 89 and defined in Drupal\Core\Render\MainContent\AjaxRenderer->renderResponse() (line 45 of /Library/WebServer/Documents/aaep/web/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php).

このエラーは、$ form ['column']がblockForm関数でコンテナーとして作成されているにもかかわらずnullを返すために発生すると考えられています。私は他の方法でコールバックを呼び出しようとしました

'#ajax' => [
    'callback' => '::columnCallback',
]

そして

'#ajax' => [
    'callback' => [$this, '\Drupal\my_examples\Plugin\Block\AJAXexample::columnCallback'],
]

しかし、私は同じエラーを受け取ります。奇妙なことに、コールバックを変更して$ form ['column']だけでなく$ form全体を返すと、フォームが繰り返され(フォームのコピーが現在のフォームの下に表示されます)、まだ適切な列数がありません。


タイプミスかもしれませんが、二重チェックがあります。columnCallbackでは、最初の引数がタイプミス(配列と&$ formの間にスペースがない)であることを知っていますか?
ケビン

回答:


4

最初の問題は、列番号の値を処理することです。最初のビルドでは構成から取得し、再構築ではユーザー入力から取得してに配置し$columnNumます。

2番目は、フォームのどの部分がAJAXで変更されるかを決定し、これをidを持つdivコンテナに入れることcolumns-wrapperです。

class AJAXexample extends BlockBase {
    public function blockForm($form, FormStateInterface $form_state) {
        $columnNum = empty($form_state->getValue('columnNum')) ? $this->configuration['columnNum'] : $form_state->getValue('columnNum');
        $form['columnNum'] = [
            '#title'   => t('Number of Columns'),
            '#type'    => 'select',
            '#options' => [
                1         => '1',
                2         => '2',
                3         => '3',
                4         => '4',
            ],
            '#default_value' => $this->configuration['columnNum'],
            '#empty_option'  => t('-select-'),
            '#ajax'          => [
                'callback'      => [$this, 'columnCallback'],
                'wrapper'       => 'columns-wrapper', 
            ],
        ];
        $form['column'] = [
            '#type' => 'container',
            '#attributes' => ['id' => 'columns-wrapper'],
        ];
        for ($i = 0; $i < $columnNum; $i += 1) {
            $form['column'][$i] = [
                $i => [
                    '#type'       => 'details',
                    '#title'      => t('Column '.$numTitle),
                    '#open'       => FALSE,
                    'columnTitle' => [
                        '#type'      => 'textfield',
                        '#title'     => t('Column Title'),
                        '#value'     => $config[0]['columnTitle'],
                    ],  
                ],
            ];  
        return $form;
    }

コールバックでは、ajaxラッパーを返すだけで済みます。

public function columnCallback(array&$form, FormStateInterface $form_state) {
    return $form['column'];
}

Drupalは、すべてのajaxリクエストでフォームを再構築し$form、コールバックのパラメーターに入れます。もう一度再構築しようとしても意味がありません。


1
ajaxリクエストが呼び出された後にエラーが表示されます。'HTTP結果コード:200' StatusText:OK ResponseText:
Matt

1
テストを実行しましたdie(print_r($ form_state-> getValues())); そして、適切なcolumnNum値を適切に表示しました。それ以外の場合はエラーになります。
マット

1
デモ用にコードに変更を加えました。行番号付きのエラーメッセージなしでデバッグすることはできません。
4k4

2
@Kevinのコメントから構文エラーを削除しましたか?エラーログにPHPエラーがありますか?このような新しいコードをテストするときは、たくさんあるはずです。
4k4

2
エラーをトレースしましreturn $form['column']renderResponse()。戻り値はチェックされていないため、nullを意味します。少なくともそのフォームキーにコンテナを配置すると、このエラーを防ぐことができるため、コールバックのパラメーターリストに問題がある可能性があります。
4k4

2

コールバックによって返されたコンテンツを配置する領域のHTML 属性で構成される(の隣の)wrapperメソッドが欠落していると思います。Ajax APIをご覧ください。次に、そのようなコンテナが存在することを確認する必要があります。'#ajax'callbackidid

コード例(簡略化):

public function blockForm($form, FormStateInterface $form_state) {
    $form['wrapper'] = array(
        '#type' => 'container',
        '#attributes' => array('id' => 'data-wrapper'),
        );
    $form['wrapper']['columnNum'] = [
        '#title'   => t('Number of Columns'),
        '#type'    => 'select',
        '#options' => [1 => '1', 2 => '2'],
        '#default_value' => $this->configuration['columnNum'],
        '#ajax'          => [
            'callback'   => '::columnCallback',
            'wrapper'    => 'data-wrapper',
        ],
    ];
}
public function columnCallback(array &$form, FormStateInterface $form_state) {
    return $form['wrapper'];
}

完全なコード例については、「Drupal 8でAjaxを使用するタイプラジオのオプションを追加する方法」を参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.