Як відновити форму після виклику 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 'число'. Стовпець зворотного викликуCallback змінює змінну 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'] повертає null, незважаючи на те, що вона створена як контейнер у функції blockForm. Я намагався викликати зворотний виклик іншими способами

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

і

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

Але я отримую ту ж помилку. Що цікаво, коли я змінюю зворотний виклик, щоб повернути всю форму $ замість просто $ form ['колонка'], вона повторює форму (копія форми відображається під поточною формою) і все ще без належної кількості стовпців.


Можливо, це помилка друку, але подвійна перевірка, чи знаєте ви, що в columnCallback перший аргумент - це помилка друку (немає пробілу між масивом та & $ формою)?
Кевін

Відповіді:


4

Перша проблема - це обробити значення для номера стовпця. При першій збірці дістаньте її з конфігурації, при повторній перебудові дістаньте її з користувальницького вводу та вставте її $columnNum.

Друге - вирішити, яка частина форми змінюється в AJAX і помістити це в контейнер div з id 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:
Метт

1
Для тестових речей я здійснив штамп (print_r ($ form_state-> getValues ​​())); і він правильно відобразив належне значення NN колонки. Це просто помилки, інакше.
Метт

1
Я змінив ваш код для демонстрації. Не може допомогти з налагодженням без повідомлень про помилки з номерами рядків.
4k4

2
Ви видалили синтаксичну помилку з коментаря @ Кевіна? Чи є в журналі помилок php помилки? Під час тестування нового коду повинно бути багато.
4k4

2
Виявлена ​​помилка, це означає, що вона return $form['column']є нульовою, оскільки значення повернення стає невірно встановленим renderResponse(). Можливо, проблема зі списком параметрів зворотного виклику може бути, тому що ми помістили принаймні контейнер у цю форму ключа, і це запобігло б цю помилку.
4к4

2

Напевно, wrapperу вашому '#ajax'(поруч із callback) способі відсутній метод, що складається з idатрибута HTML області, де має бути розміщений вміст, повернутий зворотним дзвоном. Див.: API Ajax . Тоді вам потрібно переконатися, що такий контейнер idіснує.

Приклад коду (спрощено):

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'];
}

Повний приклад коду див. У розділі: Як додати більше параметра для радіо типів, використовуючи Ajax в Drupal 8 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.