Drupal - How to rebuild form after AJAX call
First problem is to handle the value for the column number. On the first build get it from configuration, on a rebuild get it from the user input and put it in $columnNum
.
The second is to decide, what part of the form changes in AJAX and put this in a div container with the 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;
}
In the callback we only need to return the ajax wrapper.
public function columnCallback(array&$form, FormStateInterface $form_state) {
return $form['column'];
}
Drupal rebuilds the form on every ajax request and puts it in the parameter $form
of the callback. It would make no sense to try to rebuild it again.
I guess you're missing wrapper
method in your '#ajax'
(next to callback
) which consist the HTML id
attribute of the area where the content returned by the callback should be placed. See: Ajax API. Then you've to make sure such container id
exist.
Code example (simplified):
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'];
}
For complete code example, see: How to Add more option for type radios use Ajax in Drupal 8.