2

When I wrap a field in a container, the field value doesn't get saved to the database. But if it lives in root, it works properly.

public function formElement(
  FieldItemListInterface $items,
  $delta,
  array $element,
  array &$form,
  FormStateInterface $form_state
) {

    $item =& $items[$delta];
    $element += array(
      #type' => 'fieldset',
    );

    /** a bunch of fields **/

    $element['concelhocontainer'] = [
      '#type' => 'container',
      '#attributes' => ['id' => 'concelhocontainer']
    ];

    /** works properly **/
    $element['concelho'] = [
      '#type' => 'select',
      '#title' => t('County'),
      '#default_value' => isset($item->concelho) ? $item->concelho : '',
      '#options' => $this->getConcelhoList()
    ];

  /** does not work
  $element['concelhocontainer']['concelho'] = [
    '#type' => 'select',
    '#title' => t('County'),
    '#default_value' => isset($item->concelho) ? $item->concelho : '',
    '#options' => $this->getConcelhoList()
  ];
  */
  return $element;
}

The problem is that the value of the second input is not saved to the database (I've confirmed it in the database).

  • Look up the #parents and #array_parents properties. – user21641 Sep 24 '17 at 4:06
  • @IvanJaros I did, but the documentation is appaling. – Tivie Sep 24 '17 at 4:34
  • If you are altering the structure of the form element you should implement \Drupal\Core\Field\WidgetBase::massageFormValues to fix it into expected format. – user21641 Sep 24 '17 at 11:44
  • Also see \Drupal\Core\Field\WidgetBase::formMultipleElements – user21641 Sep 24 '17 at 11:45
  • @IvanJaros WidgetBase::massageFormValues seems to do the trick. – Tivie Sep 24 '17 at 17:13
3

It seems Drupal adds a #tree = true property to the field parent so you need to process the data output by the form youserlf or the form nested elements will be ignored. As @IvanJaros poited out, WidgetBase::massageFormValues let's you alter the data.

public function massageFormValues(array $values, array $form, FormStateInterface $form_state)
{
  for ($i=0; $i < count($values); ++$i) {
    if (isset($values[$i]['concelhocontainer']['concelho'])) {
      $values[$i]['concelho'] = $values[$i]['concelhocontainer']['concelho'];
    }
  }
  return $values;
}
1

Life saver. massageFormValues above did the trick. Only that I had to get my values from $form_state->getUserInput() and store them in a new $values = array()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.