Drupal 8 Ajax Callbacks misbehaving when form element in table I have a form containing the following element:

  $form['check'] = array(
    '#type' =&gt; 'checkbox',
    '#title' =&gt; t('Test'),
    '#ajax' =&gt; array(
      'callback' =&gt; array($this, 'updateTestCallback'),
      'event' =&gt; 'change',
    ),
  );


With the following simple Ajax handler:

  public function updateTestCallback(array $form, FormStateInterface $form_state) {
    $triggering_element = $form_state-&gt;getTriggeringElement();
    $ajax_response = new AjaxResponse();
    $ajax_response-&gt;addCommand(new AlertCommand($triggering_element['#name']." = ".$triggering_element['#value']));
    return $ajax_response;
  }


This works perfectly when the control is on a plain form, but I want to have a checkbox on every row of a table, and this is where I'm having problems.

I tried using a #table entity, and the checkboxes display correctly, but the Ajax callback event only gets called on every other click (i.e. one click it works, the next nothing happens, the next it works again).

So I should the problem might stem from from the #table entity, so I changed the form to build the table manually using #prefix and #suffix containing the table elements, but this is behaving exactly the same way, so it seems to be the presence of the table elements rather than the way they were generated that's causing the problem.

Here's the current build_form function:

  public function buildForm(array $form, FormStateInterface $form_state, $mid = NULL, $key = NULL) {
    $form = array(
      '#prefix' =&gt; '&lt;div id="memberform"&gt;',
      '#suffix' =&gt; '&lt;/div&gt;',
    );

    // Test checkboxes outside table:    
    $form['check'] = array(
      '#type' =&gt; 'checkbox',
      '#title' =&gt; t('Test'),
      '#ajax' =&gt; array(
        'callback' =&gt; array($this, 'updateTestCallback'),
        'event' =&gt; 'change',
      ),
    );
    $form['check2'] = array(
      '#type' =&gt; 'checkbox',
      '#title' =&gt; t('Test2'),
      '#ajax' =&gt; array(
        'callback' =&gt; array($this, 'updateTestCallback'),
        'event' =&gt; 'change',
      ),
    );

    $form['table'] = array(
      '#prefix' =&gt; '&lt;table id="member-list"&gt;',
      '#suffix' =&gt; '&lt;/table&gt;',
    );      

    $form['table']['tbody'] = array(
      '#prefix' =&gt; '&lt;tbody&gt;',
      '#suffix' =&gt; '&lt;/tbody&gt;',
    );
    // Retrieve data and builr one table row per record.
    foreach ($entries = MyStorage::myListLoad() as $entry) {
      $mid = $entry['mid'];
      $is_paid = $entry['is_paid'];
      $row = array(
        '#prefix' =&gt; '&lt;tr&gt;',
        '#suffix' =&gt; '&lt;/tr&gt;',
      );
      $row['first_name'] = array(
        '#markup' =&gt; SafeMarkup::checkPlain($entry['first_name']),
        '#prefix' =&gt; '&lt;td&gt;',
        '#suffix' =&gt; '&lt;/td&gt;',
      );
      $row['last_name'] = array(
        '#markup' =&gt; SafeMarkup::checkPlain($entry['last_name']),
        '#prefix' =&gt; '&lt;td&gt;',
        '#suffix' =&gt; '&lt;/td&gt;',
      );
      $row["is_approved_".$mid] = array(
        //'#attributes' =&gt; array('name' =&gt; 'is_approved_'.$mid, 'id' =&gt; 'edit_is_approved_'.$mid),
        '#type' =&gt; 'checkbox',
        '#title' =&gt; t('Is Approved'),
        '#title_display' =&gt; 'invisible',
        '#ajax' =&gt; array(
          'callback' =&gt; array($this, 'updateTestCallback'),
          'event' =&gt; 'change',
        ),
        '#prefix' =&gt; '&lt;td&gt;',
        '#suffix' =&gt; '&lt;/td&gt;',
      );
      $form['table']['tbody'][$mid] = $row;
    }
    return $form;
  }


Has anyone come across this problem, and can you suggest a way around it?

James
It's hard to tell without seeing some code of the table. There is probably an error in the structure of the form array. All form elements must have the correct key in the array, which correspondent with the #name. And this keys and names must be unique in the whole form. If you put a form element in a table, use an extra layer to give the element the right key.