How to add rows to a form table with AJAX Callback in Drupal 8 I try to implement a button to add rows to a form table.
Each clic on the button should add a new line.

My problem is that my modifications in the AJAX Callback doesn't seem to modify the actual $form object : 

At the first clic, row n°6 is added but without default values, wich is already a problem. The next clics have no effect, the $form parameter in the callback doesn't contain the 6th row.

What is the way to actually modify $form ?

Here is the build form :

public function buildForm(array $form, FormStateInterface $form_state, Array $profile = NULL) {

$form['submit'] = array(
    '#type' =&gt; 'submit',
    '#value' =&gt; t('Submit'),
);      

// table
$form['myTable'] = array(
'#type' =&gt; 'table',
'#header' =&gt; array(t('COL 1'), t('COL 2'), t('COL 3')),
'#prefix' =&gt; '&lt;div id="my-table-wrapper"&gt;',
'#suffix' =&gt; '&lt;/div&gt;',
);
// Build the table rows and columns.
for ($cpt = 0; $cpt &lt;= 5; $cpt++) {
// Table row
$form['myTable'][$cpt] = $this-&gt;getTableLine($cpt);
}
$form['addRow'] = array(
    '#type' =&gt; 'button',
    '#value' =&gt; t('Add a row'),
    '#ajax' =&gt; array(
            'callback' =&gt;  '::ajaxAddRow',
            'event' =&gt; 'click',
            'wrapper' =&gt; 'my-table-wrapper',
    ),
);

return $form;

}


Here the function called to fill the rows :

function getTableLine($key) {
    $line = array();

    $line['col_1'] = array(
            '#type' =&gt; 'textfield',
            '#default_value' =&gt; 'col 1 - row ' . $key,
    );
    $line['col_2'] = array(
            '#type' =&gt; 'textfield',
            '#default_value' =&gt; 'col 2 - row ' . $key,
    );
    $line['col_3'] = array(
            '#type' =&gt; 'textfield',
            '#default_value' =&gt; 'col 3 - row ' . $key,
    );
    return $line;
}


And the Ajax callback :

function ajaxAddRow($form, $form_state) {
    $cpt=0;
    for ($x = 0; $x &lt;= 10 &amp; $form['myTable'][$x]; $x++) {
        $cpt++;
    }

    // $cpt always return 6 - expected to increment
    // $form['myTable'][$cpt] is always empty

    $form['myTable'][$cpt] = $this-&gt;getTableLine($cpt);

    return $form['myTable'];

}
Details and Warnings
  
  Changes to the form must only be made in the form builder function
  (ajax_example_autocheckboxes() in the example here), or validation
  will fail. The callback function must not alter the form or any other
  state.


Reference: https://www.drupal.org/docs/7/api/javascript-api/ajax-forms-in-drupal-7

It's for D7, but the concept how Ajax works has not changed:


  The Big Idea 
  
  The big idea here is that:
  
  
  Your form gets rebuilt when you manipulate a form element (e.g. select, submit etc.)
  Your form builder function builds it a different way based on that input ($form_state)
  Your #ajax settings and your callback function arrange to deliver all or a part of the newly rebuilt form to replace or otherwise
  enhance some part of the page.