Cách xây dựng lại biểu mẫu sau cuộc gọi AJAX


12

Tôi đang cố gắng cho phép người dùng tự động chọn một số trường dựa trên hộp thả xuống bằng cách sử dụng cuộc gọi ajax, nhưng dường như tôi không thể nhận được cuộc gọi ajax để xây dựng lại biểu mẫu sau đó.

<?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;
    }
}

Số lượng trường văn bản dựa trên biến 'số' của form_state. Cột gọi lạiCallback thay đổi biến form_state thành 10 và được kích hoạt khi trường biểu mẫu 'cộtNum' được thay đổi. Tuy nhiên, biểu mẫu không được xây dựng lại với số lượng trường mới mặc dù $ form_state-> setRebuild (); được gọi là. Có cách nào để lấy lại biểu mẫu sau khi gọi ajax không?

LƯU Ý: Tôi đã thử các kỹ thuật như thay thế hoặc nối thêm các mục của biểu mẫu bên trong lệnh gọi ajax thực tế nhưng khi điều đó xảy ra, không có đầu vào nào trong các trường được thay thế được chuyển đến $ form_state.

CẬP NHẬT: Sau khi thử giải pháp của 4k4, tôi gặp lỗi

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).

Người ta tin rằng lỗi xảy ra do $ form ['cột'] đang trả về null mặc dù được tạo như một thùng chứa trong hàm blockForm. Tôi đã cố gọi lại cuộc gọi theo những cách khác như

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

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

Nhưng tôi nhận được lỗi tương tự. Thật kỳ lạ, khi tôi thay đổi cuộc gọi lại để trả về toàn bộ biểu mẫu $ thay vì chỉ biểu mẫu $ ['cột'], nó lặp lại biểu mẫu (một bản sao của biểu mẫu xuất hiện bên dưới biểu mẫu hiện tại) và vẫn không có số cột thích hợp.


Có thể là một lỗi đánh máy nhưng kiểm tra hai lần, bạn có biết rằng trong cộtCallback, đối số đầu tiên là một lỗi đánh máy (không có khoảng trắng giữa mảng và dạng $ &)?
Kevin

Câu trả lời:


4

Vấn đề đầu tiên là xử lý giá trị cho số cột. Trong bản dựng đầu tiên lấy nó từ cấu hình, trên bản dựng lại lấy nó từ đầu vào của người dùng và đặt nó vào $columnNum.

Thứ hai là quyết định, phần nào của biểu mẫu thay đổi trong AJAX và đặt phần này vào thùng chứa div với 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;
    }

Trong cuộc gọi lại, chúng ta chỉ cần trả về trình bao bọc ajax.

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

Drupal xây dựng lại biểu mẫu trên mỗi yêu cầu ajax và đặt nó trong tham số $formcủa cuộc gọi lại. Sẽ vô nghĩa khi cố gắng xây dựng lại nó một lần nữa.


1
Tôi nhận được một lỗi sau khi yêu cầu ajax được gọi. 'Mã kết quả HTTP: 200' StatusText: OK Phản hồi:
Matt

1
Những điều kiểm tra tôi đã thực hiện một die (print_r ($ form_state-> getValues ​​())); và nó đã hiển thị đúng giá trị cộtNum thích hợp. Nó chỉ lỗi khác.
Matt

1
Tôi đã đặt các thay đổi trong mã của bạn để trình diễn. Không thể giúp gỡ lỗi mà không có thông báo lỗi với số dòng.
4k4

2
Bạn đã xóa lỗi cú pháp khỏi nhận xét của @ Kevin chưa? Có lỗi php trong nhật ký lỗi không? Cần có nhiều khi thử nghiệm mã mới như thế này.
4k4

2
Theo dõi lỗi, nó có nghĩa return $form['column']là null, vì giá trị trả về không được kiểm tra renderResponse(). Vẫn có thể là một vấn đề với danh sách tham số của cuộc gọi lại, bởi vì chúng tôi đã đặt ít nhất một vùng chứa trong khóa biểu mẫu đó và điều này sẽ ngăn lỗi này.
4k4

2

Tôi đoán bạn đang thiếu wrapperphương thức trong '#ajax'(bên cạnh callback) bao gồm idthuộc tính HTML của khu vực nơi nội dung được gọi lại sẽ được đặt. Xem: API Ajax . Sau đó, bạn phải chắc chắn rằng container idtồn tại.

Ví dụ mã (đơn giản hóa):

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

Để biết ví dụ mã hoàn chỉnh, hãy xem: Cách thêm tùy chọn cho radio loại sử dụng Ajax trong Drupal 8 .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.