Score:0

entity_form how to programmatically add references and update the form visually (entity_browser)

gr flag

I´m having an fieldable entity with a reference field to paragraphs field_paragraphs and a paragraph_type with a reference field to content_type event field_events.

What i am trying in the entity form is to have a button in the paragraph_type event subform which on click prefills the field_events of the paragraph_type with content. The form display of field_events uses an entity_browser to let the user also manually choose or deselect programmatically added events and i guess this is where I am stuck.

I think i am pretty close to the solution, let me try to describe:

When clicking the button, the added events are not visible, if I use the entity_browser now to insert an event, all the events that i programmatically added get displayed.

So I somehow need to tell the entity_browser in my callback to return the updated list, i guess (I´m a Drupal beginner, so please go easy on me) But I have no clue how to do so, also i think it should be possible without doing so? I mean just add the references and let the "form rebuild independently of the form display" ... I dont know, here is the code so far:

/**
 * Implements hook_field_widget_WIDGET_TYPE_form_alter().
 */
function module_field_widget_paragraphs_form_alter(&$element, &$form_state, $context) {

  switch ($element['#paragraph_type']) {
   case 'events':

      $replace_id = $element['subform']['field_events']['widget']['#id'];

      $element["subform"]['add_tomorrows_events_button'] = [
        '#type' => 'button',
        '#attributes' => [
          'name' => 'add_tomorrows_events',
        ],
        '#value' => t('Add tomorrows events'),
        '#ajax' => [
          'callback' => 'module_insert_tomorrows_events_into_paragraph_events',
          'wrapper' => $replace_id,
          'method' => 'replace',
          'event' => 'click',
        ]
      ];

     break;

   default:
     // code...
     break;
 }

}

/**
 * Ajax callback.
 */
function module_insert_tomorrows_events_into_paragraph_events( &$form, FormStateInterface &$form_state) {

  /* Get the index of the paragraph in field_paragraphs */
  $triggering_element = $form_state->getTriggeringElement();
  $paragraph_index = $triggering_element["#parents"][1];


  /* For now just try to add 10 events */
  $results = \Drupal::entityQuery('node')
  ->condition('type', 'event')
  ->range(0, 10)
  ->execute();

  /* Here I´m trying to build up the string like it is in the target_id key of the widget 
     e.G "node:3213 node:54354 node:432423"
  */
  $target_ids = "";
  foreach ($results as $res) {
    $target_ids .= " node:".$res;
  }


  

  $form["field_paragraphs"]['widget'][$paragraph_index]["subform"]["field_events"]["widget"]["target_id"]['#value'] = $target_ids;

  /* just other stuff i tried */
  /*$form["field_paragraphs"]['widget'][$paragraph_index]["subform"]["field_events"]["widget"]["target_id"]['#default_value'] = $target_ids;*/
  /*  $form_state->setValue(['field_paragraphs', $paragraph_index, 'subform', 'field_events', 'target_id'], $target_ids);
  $form_state->setRebuild(true);
    */
/* tried to update the EB but `current` is not updated :/
   $t = EntityReferenceBrowserWidget::updateWidgetCallback($form, $form_state); 
   return $t["field_paragraphs"]["widget"][$paragraph_index]["subform"]["field_events"]["widget"];
*/




  return $form["field_paragraphs"]['widget'][$paragraph_index]["subform"]["field_events"]["widget"];
}

TL;DR: The events get added but the entity_form/entity_browser is not updated visually, after using the entity_browser all programmatically added events get displayed, how to display them in the first place?

Score:0
gr flag

I got it working, i´m sharing this if anybody stumbles across the same, in the end it was trivial with using ReplaceCommand and InvokeCommand

function module_field_widget_paragraphs_form_alter(&$element, &$form_state, $context) {
  switch ($element['#paragraph_type']) {
    case 'paragraph_events':

      // Add the button only if the paragraph-subform is expanded.
      if ($element['top']['summary']['fields_info']['#expanded']) {
        $element["subform"]['add_tomorrows_events_button'] = [
          '#type' => 'button',
          '#attributes' => [
            'name' => 'add_tomorrows_events',
          ],
          '#value' => t('insert tomorrows events'),
          '#ajax' => [
            'callback' => '_module_insert_tomorrows_events_into_paragraph_events',
            'event' => 'click',
          ],
        ];
      }

      break;


      ...

and the callback

function _module_insert_tomorrows_events_into_paragraph_events(&$form, FormStateInterface $form_state): AjaxResponse {

  $triggering_element = $form_state->getTriggeringElement();
  $paragraph_index = $triggering_element["#parents"][1];


  // Load results from view.
  $view = Views::getView('events');
  if (!$view || !array_key_exists('tomorrows_events', $view->storage->get('display'))) {
    return "view \"events\" or display \"tomorrows_events\" is missing";
  }

  $view->setDisplay('tomorrows_events');
  $view->execute();
  $results = $view->result;

  $target_ids = "";
  foreach ($results as $res) {
    $target_ids .= " node:" . $res->nid;
  }


  $form["field_paragraphs"]['widget'][$paragraph_index]["subform"]["field_events"]["widget"]["target_id"]['#value'] = $target_ids;
  $response = new AjaxResponse();

  $sel = '#' . $form["field_paragraphs"]["widget"][$paragraph_index]["subform"]['field_events']['widget']['target_id']["#id"];
  $response->addCommand(new ReplaceCommand($sel, $form["field_paragraphs"]["widget"][$paragraph_index]["subform"]['field_events']['widget']['target_id']));
  $response->addCommand(new InvokeCommand($sel, 'trigger', ['entity_browser_value_updated']));

  return $response;

}
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.