Score:0

How to retrieve #tree values inside a form?

cn flag

I am new at Drupal 8 and I am creating a module that has a #tree form. I chose #tree form to create multiple forms which has the same textfields and button.

I came across one document in drupal about #tree.
https://www.drupal.org/docs/7/api/form-api/tree-and-parents
I have made a researched about it and can't find any documentation, post or blog on how to get a specific value from #tree.

I have implemented the #tree in my form. The only problem is that I can't retrieve a specific value from the form.

for($counter = 0; $counter < $rowCount; $counter++){
   $form['firstname']['#tree'] = TRUE;
   $form['firstname'] => [
        '#type' => 'textfield',
        '#title' => 'First name',
   ];
   $form['secondname'] => [
        '#type' => 'textfield',
        '#title' => 'Second name',
   ];
   $form['save'] => [
        '#type' => 'submit',
        '#value' => $this->t('Save'),
        '#submit' => ['::submitForm'],
   ];
}

The rowCount pertains to the row in my database. The process is to acquire firstname and lastname from the user and those variables will be saved inside the database.

How can I get the 2nd firstname inside the #tree form?

Score:0
de flag

#tree Creates a hierarchy of values in the submit handler of a form.

Compare:

public function buildForm(array $form, FormStateInterface $form_state) {
  $form['container'] = [
    '#type' => 'container',
  ];
  $form['container']['some_value'] = [
    '#type' = >'textfield',
  ];

  // Submit buttons etc. not shown

  return $form;
}

This will create a form element. After clicking submit, the key of the form element is used to return the value. in this case, the key is some_value, meaning validation and submit handlers can retrieve the submitted value with form_state->getValue('some_value').

Now, add #tree to the container:

public function buildForm(array $form, FormStateInterface $form_state) {
  $form['container'] = [
    '#type' => 'container',
    '#tree' => TRUE,
  ];
  $form['container']['some_value'] = [
    '#type' = >'textfield',
  ];

  // Submit buttons etc. not shown

  return $form;
}

With this change, $form_state->getValue('some_value') will return nothing, as the value is now part of the container element (the #tree element) and needs to be retrieved relative to that:

// Returns an array with a single key, 'some_value', that contains the
// submitted value.
$form_state->getValue('container')

// Returns the submitted value:
$form_state->getValue(['container', 'some_value'])
Jeirod avatar
cn flag
Thank you for the additional information. I am using a loop that has multiple submit buttons.
Score:0
cn flag

#tree denotes a hierarchy in the form, you still need valid and logical PHP to make it work, e.g.

// In the build...
$form['parent'] = [
  '#type' => 'container',
  '#tree' => TRUE,
];

for($counter = 0; $counter < $rowCount; $counter++){
  $form['parent'][$counter] = [
    'firstname' => ['#type' => 'input', ...],
    'lastname' => ['#type' => 'input', ...],
  ];
}

// In the submit...
// '0' is the key you set with $counter previously.
$first_firstname = $form_state->getValue('parent')[0]['firstname'];
$first_lastname = $form_state->getValue('parent')[0]['lastname'];
Jeirod avatar
cn flag
thank you for the clarification. The first time I read the article in Drupal, I thought that `#tree` is a type of form in Drupal. Can I also change 0 according to the what button did the user clicked? Lets say the user clicked the 2nd submit button. Is it possible to place a hidden field that holds the number of counter to be passed at function `submit`?
cn flag
You need to set a unique `#name` for each button, and check `$form_state-> getTriggeringElement()` in the submit handler
Jeirod avatar
cn flag
thank you for the reply. I also have another question. I have created another 2 containers inside the parent container. I add containers for divisions. Can I access the value like `$first_firstname = $form_state->getValue('parent')[0]['secondContainer']['thirdContainer']['firstname'];`? I have tried this in my code and it says undefined index: firstname.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.