I am battling with D8 ajax right now, hoping someone can shed some light on where I'm badgering this implementation.
The goal is to update a value based on the on the state of a checkbox. The issue seems to be that there are multiple instances of this same form on the page. However, I've confirmed they all have unique build ids. They do have the same $form['#form_id']
, but I think that's to be expected, $form['#id']
is different.
Here is the code:
public function buildForm(array $form, FormStateInterface $form_state) {
$widget = $form_state->getBuildInfo();
/* @var $widget Factorywidget */
$widget = current($widget['args']);
if ($form_state->has('widget_id')) {
$widget_id = $form_state->get('widget_id');
}
else {
$form_state->set('widget_id', $widget->id());
}
$ajax = [
'wrapper' => 'widget-toggle-status-wrapper',
'callback' => '::ajaxRebuildForm'
];
$form['#prefix'] = '<div id="' . $ajax['wrapper'] . '">';
$form['#suffix'] = '</div>';
$form['toggle_widget_status'] = [
'#type' => 'checkbox',
'#title' => 'Toggle Status',
'#default_value' => $widget->field_widget_status->value,
'#ajax' => $ajax + ['trigger_as' => ['name' => 'widget_toggle_submit']],
];
$form['widget_id'] = [
'#type' => 'textfield',
'#default_value' => $form_state->get('widget_id'),
'#title' => 'widget ID is',
'#size' => 10,
'#disabled' => TRUE,
];
$form['widget_toggle_submit'] = [
'#type' => 'submit',
'#name' => 'widget_toggle_submit',
'#value' => $this->t('Submit'),
'#submit' => ['::widgetToggleSubmit'],
'#limit_validation_errors' => [],
'#ajax' => $ajax,
'#attributes' => [
'class' => ['js-hide']
]
];
return $form;
}
/**
* Ajax submit handler that will return the whole form structure.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return array
* The form structure.
*/
public function ajaxRebuildForm(array &$form, FormStateInterface $form_state) {
return $form;
}
public function widgetToggleSubmit($form, FormStateInterface $form_state) {
$widget = $form_state->get('widget_id');
$form_state->setRebuild();
/* @var $widget Factorywidget */
//$widget = FactorywidgetService::toggleFactorywidgetwidgetStatus($widget);
//return new AjaxResponse();
}
Again, there are multiple instances of this form on the page. I added in widget_id
as a textfield just to see if the widget Id was correct. When viewing the page, widget ID in the textfield is correct:
The problem is, no matter what toggle I click, the widget_id
in $widget = $form_state->get('widget_id');
in widgetToggleSubmit
is always the widget Id for the first form on the page. I added a shuffle to the render array which displays these to confirm - it's always set to the first form on the page.
To, hopefully illustrate, this screenshot shows the Debugger for a breakpoint I put in widgetToggleSubmit
at $form_state->setRebuild()
:
The toggle has been triggered for the widget with id 3, but $form_state->get('widget_id')
will only return the value for the first form on the page.