0

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?

1 Answer 1

0

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;

}

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.