Drupal - How to pass current selection to entity browser select view

The Entity Browser doesn't current pass current default value items field in persistent data, but it's easy to add it.

1) Add persistent data using field_widget_form_alter()

/**
 * Implements hook_field_widget_form_alter().
 */
function mymodule_field_widget_form_alter(&$element, FormStateInterface &$form_state, $context) {
  if (!empty($element['entity_browser'])) {
    $default_value =  $element['entity_browser']['#default_value'];
    $ids = [];
    foreach ($default_value as $entity) {
      $ids[] = $entity->id();
    }
    $element['entity_browser']['#widget_context']['current_ids'] = implode('+', $ids);
  }
}

2) Update your selection so that if blank it shows all:

  /**
   * {@inheritdoc}
   */
  public function getArgument() {
    $argument = NULL;
    $current_request = $this->view->getRequest();

    // Check if the widget context is available.
    if ($current_request->query->has('uuid')) {
      $uuid = $current_request->query->get('uuid');
      if ($storage = $this->selectionStorage->get($uuid)) {
        if (!empty($storage['widget_context']['current_ids'])) {
          $argument = $storage['widget_context']['current_ids'];
        }
        else {
          $argument = 'all';
        }
      }
    }
    return $argument;
  }

3) Make sure you have "exclude" and "allow multiple" checked on your selection.

enter image description here

By the way, if you update to the latest dev release of entity_browser, you don't need your custom plugin. There is a new entity_browser_widget_context default value views plugin that is configurable.

I also added an issue to the entity_browser queue to add this information when in the widget_context.


I used your default argument class and debugged a little. This is my approach:

The entity browser widget stores selected values in its current property, which is filled, when the entity form is opened with an existing entity/selection. The widget also uses AJAX when the modal closes and the current property is updated accordingly.

So you can get the selected entity IDs using something like the following in your entity form/form alter:

use Drupal\Core\Render\Element;

// Current selection. Replace 'field_references' with the actual
// name of your field.
$selection = [];
if (isset($form['field_references']['widget']['current'])) {
  $current = $form['time_records']['widget']['current'];
  foreach (Element::children($current) as $key) {
    if (isset($current[$key]['target_id']['#value'])) {
      $selection[] = $current[$key]['target_id']['#value'];
    }
  }
}

Another widget property available in the form is the widget context of the used entity browser. You can simply add the current selection to the widget context and use this information with your views default argument (the widget context is updated in the selection storage on each AJAX reload of the widget/form):

$form['field_references']['widget']['entity_browser']['#widget_context']['current_selection'] = $selection;

Then alter your EntityBrowserSelection::getArgument():

  /**
   * {@inheritdoc}
   */
  public function getArgument() {
    $argument = NULL;
    $current_request = $this->view->getRequest();

    // Check if the widget context is available.
    if ($current_request->query->has('uuid')) {
      $uuid = $current_request->query->get('uuid');
      if ($storage = $this->selectionStorage->get($uuid)) {
        if (!empty($storage['widget_context']['current_selection'])) {
          $selection = $storage['widget_context']['current_selection'];
          if (is_string($selection)) {
            $argument = $selection;
          }
          elseif (is_array($selection)) {
            $non_scalar = array_filter($selection, function ($item) {
              return !is_scalar($item);
            });
            if (empty($non_scalar)) {
              // Replace the ',' with '+', if you like to have an
              // OR filter rather than an AND filter.
              $argument = implode(',', $selection);
            }
          }
        }
      }
    }
    return $argument;
  }

With these changes I was able to filter selected items from my view with a contextual filter for the entity IDs, choosing

  • When the filter is not available: Provide a default value, Type "Entity Browser Selection"
  • More: Exclude

Hope it helps!

Tags:

8