1

In a node edit form, I am trying to add items to a multivalue field with unlimited cardinality in a form builder hook, like form_alter or after_build. I can't figure out how to do it, though, at least not very well. For instance, if I fill in the default blank item in form_alter and then add a new blank item, when you click the "Add another item" button, the form resets the items_count for the field to the original entity item count. It doesn't "see" the new blank item I added to the field, so visibly it ends up doing nothing. There's also strange results on Submit if there's a validation error.

Is there a way to do this? Not in response to clicking on a button, so not in a submit function. I think that may be the problem. That items count is in the form state storage, and from what I've seen searching around, trying to change form state in a form builder function doesn't work. I may be misunderstanding that, though.

For context, the task I'm trying to accomplish is that I have two related fields. One is an entity reference, one is an unlimited text field. A value from the referenced entity needs to always be one of the values in the unlimited text field. So when I build the form, I need to add that value to the list if it isn't there, and still end up with a blank item at the bottom of the list.

3

1 Answer 1

3

You can add or remove items in hook_ENTITY_TYPE_prepare_form() before the form is built:

/**
 * Implements hook_ENTITY_TYPE_prepare_form() for nodes.
 */
function mymodule_node_prepare_form(\Drupal\node\NodeInterface $node, $operation, \Drupal\Core\Form\FormStateInterface $form_state) {
  if ($node->getType() != 'my_content_type') {
    return;
  }
  if ($operation == 'edit') {
    // remove item
    $node->field_foo->removeItem($delta);
    // add items
    $node->field_foo[] = ['value' => $value];
    $node->field_reference[] = ['target_id' => $tid];
  }
}
4
  • Yes, this is interesting. The doc says "It is invoked just once when first building the entity form. Rebuilds will not trigger a new invocation." Apparently the entity form does get reconstructed if not officially "rebuilding" on the first ajax action (like the Add another button or an onChange event), but not thereafter. That's exactly the times when it is resetting the field items count from the entity, though, so changing the entity beforehand seems like it should solve that. Dec 29, 2022 at 17:29
  • 1
    You don't have to worry about that, it's true that Drupal starts with caching Ajax forms only after the first Ajax action. Until then any code you write preparing and altering the entity form is executed at least two times, and has to produce every time the same result. After that the form object including the entity object is cached and modified on each submit.
    – 4uk4
    Dec 29, 2022 at 18:00
  • Right, the ajax action is a new request. So it's the form being cached that is making the difference, OK. In the ajax call of the prepare hook, the form state has input values that match what was on the form, so I can use that to distinguish the two calls. Dec 29, 2022 at 18:16
  • As said, you don't have to worry. For the form logic this is not relevant, only if you do other things not connected to the form.
    – 4uk4
    Dec 29, 2022 at 19:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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