Submitting a form with ajax, when multiple instances of the same form are on a page 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-&gt;getBuildInfo();
  /* @var $widget Factorywidget */
  $widget = current($widget['args']);

  if ($form_state-&gt;has('widget_id')) {
    $widget_id = $form_state-&gt;get('widget_id');
  }
  else {
    $form_state-&gt;set('widget_id', $widget-&gt;id());
  }

  $ajax = [
    'wrapper' =&gt; 'widget-toggle-status-wrapper',
    'callback' =&gt; '::ajaxRebuildForm'
  ];

  $form['#prefix'] = '&lt;div id="' . $ajax['wrapper'] . '"&gt;';
  $form['#suffix'] = '&lt;/div&gt;';

  $form['toggle_widget_status'] = [
    '#type' =&gt; 'checkbox',
    '#title' =&gt; 'Toggle Status',
    '#default_value' =&gt; $widget-&gt;field_widget_status-&gt;value,
    '#ajax' =&gt; $ajax + ['trigger_as' =&gt; ['name' =&gt; 'widget_toggle_submit']],
  ];
  $form['widget_id'] = [
    '#type' =&gt; 'textfield',
    '#default_value' =&gt; $form_state-&gt;get('widget_id'),
    '#title' =&gt; 'widget ID is',
    '#size' =&gt; 10,
    '#disabled' =&gt; TRUE,
  ];

  $form['widget_toggle_submit'] = [
    '#type' =&gt; 'submit',
    '#name' =&gt; 'widget_toggle_submit',
    '#value' =&gt; $this-&gt;t('Submit'),
    '#submit' =&gt; ['::widgetToggleSubmit'],
    '#limit_validation_errors' =&gt; [],
    '#ajax' =&gt; $ajax,
    '#attributes' =&gt; [
      'class' =&gt; ['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 &amp;$form, FormStateInterface $form_state) {
  return $form;
}

public function widgetToggleSubmit($form, FormStateInterface $form_state) {
  $widget = $form_state-&gt;get('widget_id');
  $form_state-&gt;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-&gt;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-&gt;setRebuild():

The toggle has been triggered for the widget with id 3, but $form_state-&gt;get('widget_id') will only return the value for the first form on the page.
You can do this by setting a custom form ID for each form. So you define your form like this:

class MyForm {
  protected $formId;

  public function __construct($formId) {
    $this-&gt;formId = $formId;
  }

  public function getFormId() {
    return 'my_form-' . $formId;
  }
}


Then, when you call your form, you pass a unique Form ID for each form:

$my_form = new MyForm('some-unique-id');
$form = \Drupal::formBuilder()-&gt;getForm($my_form);


Pass a different ID for each form on the page.