I am learning drupal 8. I want to create a page that contains the form "two dimensionnal" add another item. My code works well, but I have strange behavior when I add rooms to the house (in my debug logs there is a strange value from FormStateInterface :: getTriggeringElement (), see below for code and log)
Firstly: I have two structures, houses and rooms. The user can create several houses and for each house, he can create several rooms:

When I add some at home, the form works fine:

When I add some rooms to the last house, the form works fine too:

But when I add some rooms to any "last" house, the form does not work normally (in the screenshot I click once on the "added room" in block house "1", the shortcut from "house 1" became "house 2" (?! ) and click add 5 rooms (?!):

Here is my code and a strange debug log, I donโt explain why I get this value (from getTriggeringElement () in the room_addMoreSubmit callback, and this is the problem, I think)
<?php namespace Drupal\projet\Form; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; class HouseForm extends FormBase { public function getFormId(){ return 'custom_rooms_form'; } function buildForm(array $form, FormStateInterface $form_state) { $house_count = $form_state->get('house_count'); if (is_null($house_count)) { $house_count = 1; $form_state->set('house_count', $house_count); } $form['house'] = array( //'#tree' => TRUE, '#prefix' => '<div id="house-replace">', '#suffix' => '</div>' ); for ($house_delta = 0; $house_delta < $house_count; $house_delta++) { if (!isset($form['house'][$house_delta])) { $room_count[$house_delta] = $form_state->get('room_count_'.$house_delta); if (is_null($room_count[$house_delta])) { $room_count[$house_delta] = 1; $form_state->set('room_count_'.$house_delta, $room_count[$house_delta]); } dd($room_count, "room_COUNT"); $form['house'][$house_delta]['room'] = array( '#type' => 'fieldset', '#title' => t('house : '.$house_delta), //'#tree' => TRUE, '#prefix' => '<div id="room-replace-'.$house_delta.'">', '#suffix' => '</div>' ); for ($room_delta = 0; $room_delta < $room_count[$house_delta]; $room_delta++) { if (!isset($form['house'][$house_delta]['room'][$room_delta])) { $room = array( '#type' => 'textfield' ); $check = array( '#type' => 'checkbox' ); $form['house'][$house_delta]['room'][$room_delta] = array( '#type' => 'fieldset', '#title' => t('room : '.$house_delta.'.'.$room_delta), ); $form['house'][$house_delta]['room'][$room_delta]['text'] = $room; $form['house'][$house_delta]['room'][$room_delta]['check'] = $check; } } $form['house'][$house_delta]['room']['add'] = array( '#type' => 'submit', '#name' => 'add', '#value' => t('Add room'), '#attributes' => array('class' => array('field-add-more-submit'), 'house_delta' => array($house_delta)), '#submit' => array(array(get_class($this), 'room_addMoreSubmit')), '#ajax' => array( 'callback' => array($this, 'room_addMoreCallback'), 'wrapper' => 'room-replace-'.$house_delta, 'effect' => 'fade', ), ); } } $form['house']['add'] = array( '#type' => 'submit', '#name' => 'add', '#value' => t('Add house'), '#attributes' => array('class' => array('field-add-more-submit')), '#submit' => array(array(get_class($this), 'house_addMoreSubmit')), '#ajax' => array( 'callback' => array($this, 'house_addMoreCallback'), 'wrapper' => 'house-replace', 'effect' => 'fade', ), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Create'), ); return $form; } public function room_addMoreSubmit(array $form, FormStateInterface $form_state) { dd($form_state->getTriggeringElement(), "room : getTriggeringElement()"); // below, the log when I add a room to the house '1' (result see above with the last screenshot: "the house 1" became "house 2" and one click add 5 rooms) $house = $form_state->getTriggeringElement()["#array_parents"][1]; $c = $form_state->get('room_count_'.$house) + 1; $form_state->set('room_count_'.$house, $c); $form_state->setRebuild(TRUE); } public function room_addMoreCallback(array $form, FormStateInterface $form_state) { $house = $form_state->getTriggeringElement()["#array_parents"][1]; return $form['house'][$house]['room']; } public function house_addMoreSubmit(array $form, FormStateInterface $form_state) { dd($form_state->getTriggeringElement()["#array_parents"], "house : getTriggeringElement()"); $c = $form_state->get('house_count') + 1; $form_state->set('house_count', $c); $form_state->setRebuild(TRUE); } public function house_addMoreCallback(array $form, FormStateInterface $form_state) { return $form['house']; } }
The log ('dd' in room_addMoreSubmit) when I click the add room button in house 1:

When I click the add room button in house number 1, getTriggeringElement returns the add button to the parents of the array. And, as you see, the parent "2" is not "1" (house 1) Therefore, when I click the "add room" button at home 1, this is house "2", which is identified, not house "1".
I donโt understand why ... Using getTriggeringElement is not so good?