Score:1

Is there a way to add / remove items from an unlimited cardinality field in form alter / after build?

ke flag

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.

ke flag
I'd also like to be able to remove items, but that seems like a whole nother can of worms...
4uk4 avatar
cn flag
A form alter hook is too late, then the form is already built and it's very difficult to change a complex entity form. Did you try to add/remove the field items in the entity before the form is built? See https://drupal.stackexchange.com/questions/261328/unchecking-a-boolean-field-on-form-render
taggartJ avatar
cn flag
Perhaps you want to look at something like this for add more https://gist.github.com/baikho/ec206f128eff4322e29a528f741adc74
Score:3
cn flag

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];
  }
}
ke flag
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.
4uk4 avatar
cn flag
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.
ke flag
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.
4uk4 avatar
cn flag
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.
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.