Làm thế nào để vượt qua lựa chọn hiện tại cho trình duyệt thực thể chọn xem


8

Tôi đang sử dụng Trình duyệt thực thể (2.x-dev trong Drupal 8) làm tiện ích biểu mẫu cho trường cơ sở tham chiếu thực thể tùy chỉnh của thực thể tùy chỉnh. Trình duyệt thực thể được cấu hình

  • như một màn hình hiển thị,
  • với một widget
  • và không có lựa chọn hiển thị,
  • sử dụng chế độ xem với trường chọn hàng loạt trình duyệt thực thể làm widget và
  • để nối các thực thể được chọn vào lựa chọn hiện tại của trường tham chiếu.

Chọn các thực thể là làm việc tốt. Nhưng trường tham chiếu thực thể sẽ không có bất kỳ bản sao nào.

Để dễ dàng lựa chọn các thực thể mà không trùng lặp, tôi muốn lọc các thực thể đã chọn từ kết quả xem trình duyệt thực thể. Vì vậy, người dùng sẽ chỉ nhìn thấy các thực thể không được chọn.

Với mục đích này, tôi đã tạo một plugin argument_default tùy chỉnh xem hiển thị lưu trữ lựa chọn trình duyệt thực thể làm đối số mặc định ngữ cảnh cho ID thực thể:

<?php

namespace Drupal\my_module\Plugin\views\argument_default;

use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
use Drupal\views\Plugin\views\argument_default\ArgumentDefaultPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * The entity browser selection argument default handler.
 *
 * @ViewsArgumentDefault(
 *   id = "entity_browser_selection",
 *   title = @Translation("Entity Browser Selection")
 * )
 */
class EntityBrowserSelection extends ArgumentDefaultPluginBase {

  /**
   * The selection storage.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
   */
  protected $selectionStorage;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, KeyValueStoreExpirableInterface $selection_storage) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->selectionStorage = $selection_storage;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_browser.selection_storage')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function access() {
    return $this->view->getDisplay()->pluginId === 'entity_browser';
  }

  /**
   * {@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['selected_entities'])) {
          $argument = $storage['selected_entities'];
        }
      }
    }
    return $argument;
  }

}

Vấn đề tôi gặp phải là lựa chọn hiện tại trong bộ lưu trữ lựa chọn luôn trống, cho dù có bao nhiêu thực thể đã được chọn trong trường tham chiếu thực thể và ngay cả sau khi tôi hoàn thành lựa chọn phương thức và mở lại trình duyệt thực thể.

Tôi phải làm gì để hiển thị lựa chọn hiện tại trong bộ lưu trữ lựa chọn của trình duyệt thực thể?


chờ đợi, ý bạn là nếu bạn đã chọn sẵn (và đã lưu) một mục bạn không muốn mục đó hiển thị trong phương thức dưới dạng mục có thể chọn? hoặc bạn có nghĩa là không cho phép lựa chọn trùng lặp một cách nhanh chóng ... hoặc bạn có nghĩa là bạn muốn dữ liệu duy nhất trên tất cả nội dung của bạn nếu được chọn sau đó ẩn khỏi chế độ xem?
taggartJ 15/03/19

Cả hai trường hợp. Nếu thực thể là mới và phương thức được sử dụng để chọn các thực thể có liên quan, thì lựa chọn được thực hiện sẽ được lọc từ trình duyệt thực thể, sau khi nhấp lại vào nút "chọn" (trước khi thực thể được lưu). Và tất nhiên, sau khi nó đã được lưu và sắp được chỉnh sửa lại, lựa chọn hiện tại ( #default_value) cần được xem xét như là bộ lọc.
Mario Steinitz

Câu trả lời:


4

Trình duyệt thực thể không vượt qua trường mục giá trị mặc định hiện tại trong dữ liệu liên tục, nhưng thật dễ dàng để thêm nó.

1) Thêm dữ liệu liên tục bằng cách sử dụng 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) Cập nhật lựa chọn của bạn để nếu trống, nó sẽ hiển thị tất cả:

  /**
   * {@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) Đảm bảo rằng bạn đã "loại trừ" và "cho phép nhiều" được chọn trên lựa chọn của mình.

nhập mô tả hình ảnh ở đây

Nhân tiện, nếu bạn cập nhật lên bản phát hành dev mới nhất của entity_browser, bạn không cần plugin tùy chỉnh. Có một plugin mới xem giá trị mặc định entity_browser_widget_context có thể cấu hình được.

Tôi cũng đã thêm một vấn đề vào hàng đợi entity_browser để thêm thông tin này khi ở trong widget_context.


2

Tôi đã sử dụng lớp đối số mặc định của bạn và gỡ lỗi một chút. Đây là cách tiếp cận của tôi:

Tiện ích trình duyệt thực thể lưu trữ các giá trị được chọn trong thuộc tính của nó current, được điền vào, khi biểu mẫu thực thể được mở với một thực thể / lựa chọn hiện có. Tiện ích cũng sử dụng AJAX khi đóng chế độ và thuộc currenttính được cập nhật tương ứng.

Vì vậy, bạn có thể lấy ID thực thể được chọn bằng cách sử dụng một cái gì đó như sau trong biểu mẫu / biểu mẫu thực thể của bạn thay đổi:

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'];
    }
  }
}

Một thuộc tính widget khác có sẵn trong biểu mẫu là bối cảnh widget của trình duyệt thực thể được sử dụng. Bạn chỉ có thể thêm lựa chọn hiện tại vào ngữ cảnh tiện ích và sử dụng thông tin này với đối số mặc định của chế độ xem (bối cảnh tiện ích được cập nhật trong bộ lưu trữ lựa chọn trên mỗi lần tải lại AJAX của tiện ích / biểu mẫu):

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

Sau đó thay đổi 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;
  }

Với những thay đổi này, tôi có thể lọc các mục đã chọn từ chế độ xem của mình bằng bộ lọc theo ngữ cảnh cho ID thực thể, chọn

  • Khi bộ lọc không khả dụng: Cung cấp giá trị mặc định, Nhập "Lựa chọn trình duyệt thực thể"
  • Thêm: Không bao gồm

Hy vọng nó giúp!


0

Tôi không thể làm cho bộ lọc mặc định hoạt động nhưng tôi đã có một số thành công khi thực hiện công việc đáng sợ sau:

function mymodule_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == "media_entity_browser" && $view->current_display ==
    'entity_browser_1') {
    $request = \Drupal::request();
    $prams = $request->query->all();
    $is_edit = FALSE;
    if (!empty($prams['original_path'])) {
      // testing with "/node/1/edit"
      $check_explode = explode('/', $prams['original_path']);
      if (in_array('edit', $check_explode)) {
        $edit_key = array_search ( 'edit', $check_explode);
        $entity_id_key = $edit_key - 1;
        $entity_id = $check_explode[$entity_id_key];
        $entity_type_key = $edit_key - 2;
        $entity_type = $check_explode[$entity_type_key];
        $selected_ids = [];
        try {
          $entity = \Drupal::entityTypeManager()->getStorage($entity_type)->load($entity_id);
          // This sucks bacause field name is hardcoded.
          $media_entities = $entity->field_image->referencedEntities();
          if (!empty($media_entities)) {
            foreach ($media_entities as $media_entity) {
              $selected_ids[] = (int) $media_entity->id();
            }
          }
        }
        catch (\Exception $e) {
          // log this.
        }

        $my_results = [];
        // Now need to remove from view.
        if (!empty($selected_ids)) {
          $i = 0;
          foreach ($view->result as $key =>  $item) {
            $id = (int) $item->_entity->id();
            if (!in_array($id, $selected_ids)) {
              $my_results[] = new ResultRow([
                '_entity' => $item->_entity,
                'index' => $i,
                'mid' => $item->_entity->id(),
              ]);
              $i++;
            }
          }
          $view->result = $my_results;
        }
      }
    }
  }
}

Điều này không hoạt động. Tuy nhiên, có khá nhiều giả định được đưa ra ... Trình duyệt thực thể điều tốt cho phép bạn chọn chế độ xem nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.