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而不是仅返回$ form ['column']时,它会重复该表单(该表单的副本出现在当前表单下方)并且仍然没有适当的列数。


可能是拼写错误,但要仔细检查,您是否知道在columnCallback中,第一个参数是拼写错误(数组和&$ form之间没有空格)?
凯文

Answers:


4

第一个问题是处理列号的值。在第一个构建中,从配置中获取它,在重新构建中,从用户输入中获取它,并将其放入$columnNum

第二步是确定表单的哪一部分在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
我执行了一次测试的模具(print_r($ form_state-> getValues()));并且确实显示了正确的columnNum值。否则会出错。
马特

1
我将所做的更改放在您的代码中以进行演示。如果没有带行号的错误消息,将无法进行调试。
k4

2
您是否从@Kevin的注释中删除了语法错误?错误日志中是否存在php错误?在测试这样的新代码时,应该有很多东西。
4k4

2
跟踪错误,它表示return $form['column']为null,因为未检查返回值renderResponse()。回调的参数列表可能仍然是一个问题,因为我们在该表单键中至少放置了一个容器,这可以防止发生此错误。
2016年

2

我猜想wrapper'#ajax'(在旁边callback)缺少方法,该方法包含id应放置回调返回的内容的区域的HTML 属性。请参阅:Ajax API。然后,您必须确保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'];
}

有关完整的代码示例,请参见:如何在Drupal 8中使用Ajax为类型无线电添加更多选项

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.