diff --git a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
index 17dcac0a90..7832820ec3 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
@@ -164,6 +164,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
     $entity_type_id = $configuration['target_type'];
     $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
     $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
+    $selected_bundles = [];
 
     if ($entity_type->hasKey('bundle')) {
       $bundle_options = [];
@@ -200,6 +201,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
           'class' => ['js-hide'],
         ],
         '#submit' => [[EntityReferenceItem::class, 'settingsAjaxSubmit']],
+        '#element_validate' => [[static::class, 'validateTargetBundlesUpdate']],
       ];
     }
     else {
@@ -208,6 +210,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
         '#value' => [],
       ];
     }
+    $form['target_bundles']['#element_validate'][] = [static::class, 'validateTargetBundles'];
 
     if ($entity_type->entityClassImplements(FieldableEntityInterface::class)) {
       $options = $entity_type->hasKey('bundle') ? $selected_bundles : $bundles;
@@ -314,22 +317,25 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
   }
 
   /**
-   * {@inheritdoc}
+   * Validates a target_bundles element.
    */
-  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
-    parent::validateConfigurationForm($form, $form_state);
-
+  public static function validateTargetBundles($element, FormStateInterface $form_state, $form) {
     // If no checkboxes were checked for 'target_bundles', store NULL ("all
     // bundles are referenceable") rather than empty array ("no bundle is
     // referenceable" - typically happens when all referenceable bundles have
     // been deleted).
-    if ($form_state->getValue(['settings', 'handler_settings', 'target_bundles']) === []) {
-      $form_state->setValue(['settings', 'handler_settings', 'target_bundles'], NULL);
+    if ($form_state->getValue($element['#parents']) === []) {
+      $form_state->setValueForElement($element, NULL);
     }
+  }
 
+  /**
+   * Validates a target_bundles_update element.
+   */
+  public static function validateTargetBundlesUpdate($element, FormStateInterface $form_state, $form) {
     // Don't store the 'target_bundles_update' button value into the field
     // config settings.
-    $form_state->unsetValue(['settings', 'handler_settings', 'target_bundles_update']);
+    $form_state->unsetValue($element['#parents']);
   }
 
   /**
diff --git a/core/modules/views/config/schema/views.filter.schema.yml b/core/modules/views/config/schema/views.filter.schema.yml
index 1eb09007ae..26506c8e6c 100644
--- a/core/modules/views/config/schema/views.filter.schema.yml
+++ b/core/modules/views/config/schema/views.filter.schema.yml
@@ -128,6 +128,20 @@ views.filter.many_to_one:
       type: boolean
       label: 'Reduce duplicate'
 
+views.filter.entity_reference:
+  type: views.filter.many_to_one
+  label: 'Entity reference'
+  mapping:
+    sub_handler:
+      type: string
+      label: 'Selection handler'
+    widget:
+      type: string
+      label: 'Selection type'
+    sub_handler_settings:
+      type: entity_reference_selection.[%parent.sub_handler]
+      label: 'Selection handler settings'
+
 views.filter.standard:
   type: views_filter
   label: 'Standard'
diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index 0550fb213e..113d18d016 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -452,6 +452,11 @@ protected function mapFieldDefinition($table, $field_name, FieldDefinitionInterf
       $table_data[$schema_field_name] = NestedArray::mergeDeep($table_data[$schema_field_name], $this->mapSingleFieldViewsData($table, $field_name, $field_definition_type, $field_column_name, $field_schema['columns'][$field_column_name]['type'], $first, $field_definition));
       $table_data[$schema_field_name]['entity field'] = $field_name;
       $first = FALSE;
+
+      if ($field_definition_type === 'entity_reference') {
+        // Add "entity_reference" filter.
+        _views_add_entity_reference_filter_data($schema_field_name, $table_data);
+      }
     }
   }
 
diff --git a/core/modules/views/src/Plugin/views/filter/EntityReference.php b/core/modules/views/src/Plugin/views/filter/EntityReference.php
new file mode 100644
index 0000000000..2a1b8c4ff9
--- /dev/null
+++ b/core/modules/views/src/Plugin/views/filter/EntityReference.php
@@ -0,0 +1,753 @@
+<?php
+
+namespace Drupal\views\Plugin\views\filter;
+
+use Drupal\Component\Plugin\DependentPluginInterface;
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Entity\Element\EntityAutocomplete;
+use Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface;
+use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Form\SubformState;
+use Drupal\Core\Messenger\MessengerInterface;
+use Drupal\Core\Render\Element;
+use Drupal\views\FieldAPIHandlerTrait;
+use Drupal\views\Plugin\views\display\DisplayPluginBase;
+use Drupal\views\ViewExecutable;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Filters a view by entity references.
+ *
+ * @ingroup views_filter_handlers
+ *
+ * @ViewsFilter("entity_reference")
+ */
+class EntityReference extends ManyToOne {
+
+  use FieldAPIHandlerTrait;
+
+  /**
+   * Type for the autocomplete filter format.
+   */
+  const WIDGET_AUTOCOMPLETE = 'autocomplete';
+
+  /**
+   * Type for the select list filter format.
+   */
+  const WIDGET_SELECT = 'select';
+
+  /**
+   * Max number of entities in the select widget.
+   */
+  const WIDGET_SELECT_LIMIT = 100;
+
+  /**
+   * The subform prefix.
+   */
+  const SUBFORM_PREFIX = 'reference_';
+
+  /**
+   * The all value.
+   */
+  const ALL_VALUE = 'All';
+
+  /**
+   * The selection handlers available for the target entity ID of the filter.
+   *
+   * @var array
+   */
+  protected $handlerOptions;
+
+  /**
+   * Validated exposed input that will be set as the input value.
+   *
+   * If the select list widget is chosen.
+   *
+   * @var array
+   */
+  protected $validatedExposedInput;
+
+  /**
+   * The selection plugin manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface
+   */
+  protected $selectionPluginManager;
+
+  /**
+   * The entity type manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The messenger service.
+   *
+   * @var \Drupal\Core\Messenger\MessengerInterface
+   */
+  protected $messenger;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL): void {
+    parent::init($view, $display, $options);
+    if (empty($this->definition['field_name'])) {
+      $this->definition['field_name'] = $options['field'];
+    }
+
+    $this->definition['options callback'] = [$this, 'getValueOptionsCallback'];
+    $this->definition['options arguments'] = [$this->getSelectionHandler($this->options['sub_handler'])];
+  }
+
+  /**
+   * Constructs a Handler object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface $selection_plugin_manager
+   *   The selection plugin manager service.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager service.
+   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
+   *   The messenger service.
+   */
+  public function __construct(
+    array $configuration,
+    $plugin_id,
+    $plugin_definition,
+    SelectionPluginManagerInterface $selection_plugin_manager,
+    EntityTypeManagerInterface $entity_type_manager,
+    MessengerInterface $messenger
+  ) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->selectionPluginManager = $selection_plugin_manager;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->messenger = $messenger;
+
+    // @todo Unify 'entity field'/'field_name' instead of converting back and
+    // forth. https://www.drupal.org/node/2410779
+    if (isset($this->definition['entity field'])) {
+      $this->definition['field_name'] = $this->definition['entity field'];
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): EntityReference {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('plugin.manager.entity_reference_selection'),
+      $container->get('entity_type.manager'),
+      $container->get('messenger')
+    );
+  }
+
+  /**
+   * Gets the entity reference selection handler.
+   *
+   * @param string $sub_handler
+   *   The sub handler to get an instance of or NULL for the current selection.
+   *
+   * @return \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface
+   *   The selection handler plugin instance.
+   */
+  protected function getSelectionHandler($sub_handler = NULL): SelectionInterface {
+
+    // Default values for the handler.
+    $handler_settings = $this->options['sub_handler_settings'] ?? [];
+    $handler_settings['handler'] = $sub_handler;
+    $handler_settings['target_type'] = $this->getReferencedEntityType()->id();
+
+    return $this->selectionPluginManager->getInstance($handler_settings);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function defineOptions(): array {
+    $options = parent::defineOptions();
+
+    $options['sub_handler'] = [
+      'default' => 'default:' . $this->getReferencedEntityType()->id(),
+    ];
+    $options['sub_handler_settings'] = ['default' => []];
+    $options['widget'] = ['default' => static::WIDGET_AUTOCOMPLETE];
+
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasExtraOptions(): bool {
+    return TRUE;
+  }
+
+  /**
+   * Get all selection plugins for this entity type.
+   *
+   * @return string[]
+   *   The selection handlers available for the target entity ID of the filter.
+   */
+  protected function getSubHandlerOptions(): array {
+    if ($this->handlerOptions) {
+      return $this->handlerOptions;
+    }
+    $entity_type = $this->getReferencedEntityType();
+    $selection_plugins = $this->selectionPluginManager->getSelectionGroups($entity_type->id());
+    $this->handlerOptions = [];
+    foreach (array_keys($selection_plugins) as $selection_group_id) {
+      // We only display base plugins (e.g. 'default', 'views', ...).
+      if (array_key_exists($selection_group_id, $selection_plugins[$selection_group_id])) {
+        $this->handlerOptions[$selection_group_id] = (string) $selection_plugins[$selection_group_id][$selection_group_id]['label'];
+      }
+      elseif (array_key_exists($selection_group_id . ':' . $entity_type->id(), $selection_plugins[$selection_group_id])) {
+        $selection_group_plugin = $selection_group_id . ':' . $entity_type->id();
+        $this->handlerOptions[$selection_group_plugin] = (string) $selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label'];
+      }
+    }
+    return $this->handlerOptions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
+    $form['sub_handler'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Reference method'),
+      '#options' => $this->getSubHandlerOptions(),
+      '#default_value' => $this->options['sub_handler'],
+      '#required' => TRUE,
+    ];
+
+    // We store the settings from any sub handler in sub_handler_settings, but
+    // in this form, we have multiple sub handlers conditionally displayed.
+    // Copy the active sub_handler_settings into the handler specific settings
+    // to set the defaults to match the saved options on build.
+    if (!empty($this->options['sub_handler']) && !empty($this->options['sub_handler_settings'])) {
+      $this->options[static::SUBFORM_PREFIX . $this->options['sub_handler']] = $this->options['sub_handler_settings'];
+    }
+
+    foreach ($this->getSubHandlerOptions() as $sub_handler => $sub_handler_label) {
+      $subform_key = static::SUBFORM_PREFIX . $sub_handler;
+      $subform = [
+        '#type' => 'fieldset',
+        '#title' => $this->t('Reference type "@type"', [
+          '@type' => $sub_handler_label,
+        ]),
+        '#tree' => TRUE,
+        '#parents' => [
+          'options',
+          $subform_key,
+        ],
+        // Make the sub handler settings conditional on the selected selection
+        // handler.
+        '#states' => [
+          'visible' => [
+            'select[name="options[sub_handler]"]' => ['value' => $sub_handler],
+          ],
+        ],
+      ];
+
+      // Build the sub form and sub for state.
+      $selection_handler = $this->getSelectionHandler($sub_handler);
+      if (!empty($this->options[$subform_key])) {
+        $selection_config = $selection_handler->getConfiguration();
+        $selection_config = NestedArray::mergeDeepArray([
+          $selection_config,
+          $this->options[$subform_key],
+        ], TRUE);
+        $selection_handler->setConfiguration($selection_config);
+      }
+      $subform_state = SubformState::createForSubform($subform, $form, $form_state);
+      $sub_handler_settings = $selection_handler->buildConfigurationForm($subform, $subform_state);
+
+      switch ($sub_handler) {
+        case 'views':
+          if (isset($sub_handler_settings['view']['no_view_help'])) {
+            // If there are no views with entity reference displays, ViewsSelection
+            // still validates the view. This will prevent form config extra form
+            // submission, so we remove it here.
+            unset($sub_handler_settings['view']['#element_validate']);
+          }
+          break;
+
+        default:
+          // Remove unnecessary and inappropriate handler settings from the
+          // filter config form.
+          $sub_handler_settings['target_bundles_update']['#access'] = FALSE;
+          $sub_handler_settings['auto_create']['#access'] = FALSE;
+          $sub_handler_settings['auto_create_bundle']['#access'] = FALSE;
+      }
+
+      // Workaround for https://www.drupal.org/project/drupal/issues/2651418.
+      // @todo Remove the below when the referenced issue is fixed.
+      foreach (Element::children($sub_handler_settings) as $key) {
+        if (\array_key_exists('#ajax', $sub_handler_settings[$key]) &&
+          !\is_array($sub_handler_settings[$key]['#ajax'])
+        ) {
+          $sub_handler_settings[$key]['#ajax'] = [];
+        }
+
+        foreach (Element::children($sub_handler_settings[$key]) as $sub_key) {
+          if (\array_key_exists('#ajax', $sub_handler_settings[$key][$sub_key]) &&
+            !\is_array($sub_handler_settings[$key][$sub_key]['#ajax'])
+          ) {
+            $sub_handler_settings[$key][$sub_key]['#ajax'] = [];
+          }
+        }
+      }
+
+      $subform = NestedArray::mergeDeepArray([
+        $subform,
+        $sub_handler_settings,
+      ], TRUE);
+
+      $form[$subform_key] = $subform;
+      $this->removeRequiredOfSubformChildren($form[$subform_key]);
+    }
+
+    $form['widget'] = [
+      '#type' => 'radios',
+      '#title' => $this->t('Selection type'),
+      '#default_value' => $this->options['widget'],
+      '#options' => [
+        static::WIDGET_SELECT => $this->t('Select list'),
+        static::WIDGET_AUTOCOMPLETE => $this->t('Autocomplete'),
+      ],
+      '#description' => $this->t('For performance and UX reasons, the maximum count of selectable entities for the "Select list" selection type is limited to @count. If more is expected, select "Autocomplete" instead.', [
+        '@count' => static::WIDGET_SELECT_LIMIT,
+      ]),
+    ];
+  }
+
+  /**
+   * Remove the required property to prevent focus errors.
+   *
+   * @param array $element
+   *   The form element.
+   */
+  protected function removeRequiredOfSubformChildren(array &$element) {
+    if (isset($element['#required']) && $element['#required']) {
+      $element['#required'] = FALSE;
+      $element['#element_validate'][] = [static::class, 'validateRequired'];
+    }
+
+    // Recursively apply to nested fields within the handler sub form.
+    foreach (Element::children($element) as $delta) {
+      $this->removeRequiredOfSubformChildren($element[$delta]);
+    }
+  }
+
+  /**
+   * Validates that a required field for a sub handler has a value.
+   *
+   * @param array $element
+   *   The cardinality form render array.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   */
+  public static function validateRequired(array &$element, FormStateInterface $form_state): void {
+    if (!empty($element['value'])) {
+      return;
+    }
+
+    // Config extra handler does not output validation messages and
+    // closes the modal with no feedback to the user.
+    // @todo https://www.drupal.org/project/drupal/issues/3163740.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateExtraOptionsForm($form, FormStateInterface $form_state) {
+    $options = $form_state->getValue('options');
+    $sub_handler = $options['sub_handler'];
+    $subform = $form[static::SUBFORM_PREFIX . $sub_handler];
+    $subform_state = SubformState::createForSubform($subform, $form, $form_state);
+
+    // Copy handler_settings from options to settings to be compatible with
+    // selection plugins.
+    $subform_options = $form_state->getValue([
+      'options',
+      static::SUBFORM_PREFIX . $sub_handler,
+    ]);
+    $subform_state->setValue([
+      'settings',
+    ], $subform_options);
+    $this->getSelectionHandler($sub_handler)
+      ->validateConfigurationForm($subform, $subform_state);
+
+    // Store the sub handler options in sub_handler_settings.
+    $form_state->setValue(['options', 'sub_handler_settings'], $subform_options);
+
+    // Remove options that are not from the selected sub_handler.
+    foreach (array_keys($this->getSubHandlerOptions()) as $sub_handler_option) {
+      if (isset($options[static::SUBFORM_PREFIX . $sub_handler_option])) {
+        $form_state->unsetValue(['options', static::SUBFORM_PREFIX . $sub_handler_option]);
+      }
+    }
+
+    parent::validateExtraOptionsForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitExtraOptionsForm($form, FormStateInterface $form_state) {
+    $sub_handler = $form_state->getValue('options')['sub_handler'];
+
+    // Ensure that only the select sub handler option is saved.
+    foreach (array_keys($this->getSubHandlerOptions()) as $sub_handler_option) {
+      if ($sub_handler_option == $sub_handler) {
+        $this->options['sub_handler_settings'] = $this->options[static::SUBFORM_PREFIX . $sub_handler_option];
+      }
+      if (isset($this->options[static::SUBFORM_PREFIX . $sub_handler_option])) {
+        unset($this->options[static::SUBFORM_PREFIX . $sub_handler_option]);
+      }
+    }
+  }
+
+  /**
+   * Fixes the issue with switching between the widgets in the view editor.
+   *
+   * @param array $form
+   *   Associative array containing the structure of the form, passed by
+   *   reference.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   */
+  protected function alternateWidgetsDefaultNormalize(array &$form, FormStateInterface $form_state) {
+    $field_id = '_' . $this->getFieldDefinition()->getName() . '-widget';
+    $form[$field_id] = [
+      '#type' => 'hidden',
+      '#value' => $this->options['widget'],
+    ];
+
+    $previous_widget = $form_state->getUserInput()[$field_id] ?? NULL;
+    if ($previous_widget && $previous_widget !== $this->options['widget']) {
+      $form['value']['#value_callback'] = function ($element) {
+        return $element['#default_value'] ?? '';
+      };
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function valueForm(&$form, FormStateInterface $form_state) {
+    if (!isset($this->options['sub_handler'])) {
+      return;
+    }
+    switch ($this->options['widget']) {
+      case static::WIDGET_SELECT:
+        $this->valueFormAddSelect($form, $form_state);
+        break;
+
+      case static::WIDGET_AUTOCOMPLETE:
+        $this->valueFormAddAutocomplete($form, $form_state);
+        break;
+    }
+
+    if (!empty($this->view->live_preview)) {
+      $this->alternateWidgetsDefaultNormalize($form, $form_state);
+    }
+
+    // Show or hide the value field depending on the operator field.
+    $is_exposed = $this->options['exposed'];
+
+    $visible = [];
+    if ($is_exposed) {
+      $operator_field = ($this->options['expose']['use_operator'] && $this->options['expose']['operator_id']) ? $this->options['expose']['operator_id'] : NULL;
+    }
+    else {
+      $operator_field = 'options[operator]';
+      $visible[] = [
+        ':input[name="options[expose_button][checkbox][checkbox]"]' => ['checked' => TRUE],
+        ':input[name="options[expose][use_operator]"]' => ['checked' => TRUE],
+        ':input[name="options[expose][operator_id]"]' => ['empty' => FALSE],
+      ];
+    }
+    if ($operator_field) {
+      foreach ($this->operatorValues(1) as $operator) {
+        $visible[] = [
+          ':input[name="' . $operator_field . '"]' => ['value' => $operator],
+        ];
+      }
+      $form['value']['#states'] = ['visible' => $visible];
+    }
+
+    if (!$is_exposed) {
+      // Retain the helper option.
+      $this->helper->buildOptionsForm($form, $form_state);
+
+      // Show help text if not exposed to end users.
+      $form['value']['#description'] = $this->t('Leave blank for all. Otherwise, the first selected item will be the default instead of "Any".');
+    }
+  }
+
+  /**
+   * Adds an autocomplete element to the form.
+   *
+   * @param array $form
+   *   Associative array containing the structure of the form, passed by
+   *   reference.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   */
+  protected function valueFormAddAutocomplete(array &$form, FormStateInterface $form_state): void {
+    $referenced_type = $this->getReferencedEntityType();
+    $form['value'] = [
+      '#title' => $this->t('Select %entity_types', ['%entity_types' => $referenced_type->getPluralLabel()]),
+      '#type' => 'entity_autocomplete',
+      '#default_value' => EntityAutocomplete::getEntityLabels($this->getDefaultSelectedEntities()),
+      '#tags' => TRUE,
+      '#process_default_value' => FALSE,
+      '#target_type' => $referenced_type->id(),
+      '#selection_handler' => $this->options['sub_handler'],
+      '#selection_settings' => $this->options['sub_handler_settings'],
+      // Validation is done by validateExposed().
+      '#validate_reference' => FALSE,
+    ];
+  }
+
+  /**
+   * Adds a select element to the form.
+   *
+   * @param array $form
+   *   Associative array containing the structure of the form, passed by
+   *   reference.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   */
+  protected function valueFormAddSelect(array &$form, FormStateInterface $form_state): void {
+    $is_exposed = $form_state->get('exposed');
+
+    $options = $this->getValueOptions();
+    $default_value = (array) $this->value;
+
+    if ($is_exposed) {
+      $identifier = $this->options['expose']['identifier'];
+
+      if (!empty($this->options['expose']['reduce'])) {
+        $options = $this->reduceValueOptions($options);
+
+        if (!empty($this->options['expose']['multiple']) && empty($this->options['expose']['required'])) {
+          $default_value = [];
+        }
+      }
+
+      if (empty($this->options['expose']['multiple'])) {
+        if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) {
+          $default_value = static::ALL_VALUE;
+        }
+        elseif (empty($default_value)) {
+          $keys = array_keys($options);
+          $default_value = array_shift($keys);
+        }
+        else {
+          // Set the default value to be the first element of the array.
+          $default_value = reset($default_value);
+        }
+      }
+    }
+
+    $referenced_type = $this->getReferencedEntityType();
+    $form['value'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Select @entity_types', ['@entity_types' => $referenced_type->getPluralLabel()]),
+      '#multiple' => TRUE,
+      '#options' => $options,
+      // Set a minimum size to facilitate easier selection of entities.
+      '#size' => min(8, count($options)),
+      '#default_value' => $default_value,
+    ];
+
+    $user_input = $form_state->getUserInput();
+    if ($is_exposed && isset($identifier) && !isset($user_input[$identifier])) {
+      $user_input[$identifier] = $default_value;
+      $form_state->setUserInput($user_input);
+    }
+  }
+
+  /**
+   * Gets all entities selected by default.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface[]
+   *   All entities selected by default, or an empty array, if none.
+   */
+  protected function getDefaultSelectedEntities(): array {
+    $referenced_type_id = $this->getReferencedEntityType()->id();
+    $entity_storage = $this->entityTypeManager->getStorage($referenced_type_id);
+
+    return !empty($this->value) && !isset($this->value[static::ALL_VALUE]) ? $entity_storage->loadMultiple($this->value) : [];
+  }
+
+  /**
+   * Returns the value options for a select widget.
+   *
+   * @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $selection_handler
+   *   The selection handler.
+   *
+   * @return string[]
+   *   The options.
+   *
+   * @see \Drupal\views\Plugin\views\filter\InOperator::getValueOptions()
+   */
+  protected function getValueOptionsCallback(SelectionInterface $selection_handler): array {
+    $entity_data = [];
+    if ($this->options['widget'] === static::WIDGET_SELECT) {
+      $entity_data = $selection_handler->getReferenceableEntities(NULL, 'CONTAINS', static::WIDGET_SELECT_LIMIT);
+    }
+
+    $options = [];
+    foreach ($entity_data as $bundle) {
+      foreach ($bundle as $id => $entity_label) {
+        $options[$id] = $entity_label;
+      }
+    }
+
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate() {
+
+    // InOperator validation logic is not appropriate for entity reference
+    // autocomplete or select, so prevent parent class validation from
+    // occurring.
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function acceptExposedInput($input): bool {
+    if (empty($this->options['exposed'])) {
+      return TRUE;
+    }
+
+    // We need to know the operator, which is normally set in
+    // \Drupal\views\Plugin\views\filter\FilterPluginBase::acceptExposedInput(),
+    // before we actually call the parent version of ourselves.
+    if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) {
+      $this->operator = $input[$this->options['expose']['operator_id']];
+    }
+
+    // If view is an attachment and is inheriting exposed filters, then assume
+    // exposed input has already been validated.
+    if (!empty($this->view->is_attachment) && $this->view->display_handler->usesExposed()) {
+      $this->validatedExposedInput = (array) $this->view->exposed_raw_input[$this->options['expose']['identifier']];
+    }
+
+    // If we're checking for EMPTY or NOT, we don't need any input, and we can
+    // say that our input conditions are met by just having the right operator.
+    if ($this->operator == 'empty' || $this->operator == 'not empty') {
+      return TRUE;
+    }
+
+    // If it's non-required and there's no value don't bother filtering.
+    if (!$this->options['expose']['required'] && empty($this->validatedExposedInput)) {
+      return FALSE;
+    }
+
+    $accept_exposed_input = parent::acceptExposedInput($input);
+    if ($accept_exposed_input) {
+      // If we have previously validated input, override.
+      if (isset($this->validatedExposedInput)) {
+        $this->value = $this->validatedExposedInput;
+      }
+    }
+
+    return $accept_exposed_input;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateExposed(&$form, FormStateInterface $form_state) {
+    if (empty($this->options['exposed'])) {
+      return;
+    }
+
+    $identifier = $this->options['expose']['identifier'];
+
+    // Set the validated exposed input from the select list when not the all
+    // value option.
+    if ($this->options['widget'] == static::WIDGET_SELECT) {
+      if ($form_state->getValue($identifier) != static::ALL_VALUE) {
+        $this->validatedExposedInput = (array) $form_state->getValue($identifier);
+      }
+      return;
+    }
+
+    if (empty($identifier)) {
+      return;
+    }
+
+    $values = $form_state->getValue($identifier);
+    if (!is_array($values)) {
+      return;
+    }
+
+    foreach ($values as $value) {
+      $this->validatedExposedInput[] = $value['target_id'];
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function valueSubmit($form, FormStateInterface $form_state) {
+    // Prevent the parent class InOperator from altering the array.
+    // @see \Drupal\views\Plugin\views\filter\InOperator::valueSubmit().
+  }
+
+  /**
+   * Gets the target entity type referenced by this field.
+   *
+   * @return \Drupal\Core\Entity\EntityTypeInterface
+   *   The entity type definition.
+   */
+  protected function getReferencedEntityType(): EntityTypeInterface {
+    $field_def = $this->getFieldDefinition();
+    $entity_type_id = $field_def->getItemDefinition()
+      ->getSetting('target_type');
+    return $this->entityTypeManager->getDefinition($entity_type_id);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies(): array {
+    $dependencies = parent::calculateDependencies();
+
+    $sub_handler = $this->options['sub_handler'];
+    $selection_handler = $this->getSelectionHandler($sub_handler);
+    if ($selection_handler instanceof DependentPluginInterface) {
+      $dependencies += $selection_handler->calculateDependencies();
+    }
+
+    foreach ($this->getDefaultSelectedEntities() as $entity) {
+      $dependencies[$entity->getConfigDependencyKey()][] = $entity->getConfigDependencyName();
+    }
+
+    return $dependencies;
+  }
+
+}
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_entity_reference.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_entity_reference.yml
new file mode 100644
index 0000000000..669593a4ae
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_entity_reference.yml
@@ -0,0 +1,324 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - node.type.page
+  module:
+    - node
+    - user
+id: test_filter_entity_reference
+label: test_filter_entity_reference
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: none
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_comment: ''
+          query_tags: {  }
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: mini
+        options:
+          items_per_page: 10
+          offset: 0
+          id: 0
+          total_pages: null
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+          tags:
+            previous: â€¹â€¹
+            next: â€ºâ€º
+      style:
+        type: default
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          uses_fields: false
+      row:
+        type: fields
+        options:
+          inline: {  }
+          separator: ''
+          hide_empty: false
+          default_field_elements: true
+      fields:
+        title:
+          id: title
+          table: node_field_data
+          field: title
+          entity_type: node
+          entity_field: title
+          label: ''
+          alter:
+            alter_text: false
+            make_link: false
+            absolute: false
+            trim: false
+            word_boundary: false
+            ellipsis: false
+            strip_tags: false
+            html: false
+          hide_empty: false
+          empty_zero: false
+          settings:
+            link_to_entity: true
+          plugin_id: field
+          relationship: none
+          group_type: group
+          admin_label: ''
+          exclude: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+      filters:
+        status:
+          value: '1'
+          table: node_field_data
+          field: status
+          plugin_id: boolean
+          entity_type: node
+          entity_field: status
+          id: status
+          expose:
+            operator: ''
+          group: 1
+        type:
+          id: type
+          table: node_field_data
+          field: type
+          value:
+            page: page
+          entity_type: node
+          entity_field: type
+          plugin_id: bundle
+        field_test_target_id:
+          id: field_test_target_id
+          table: node__field_test
+          field: field_test_target_id_reference
+          relationship: none
+          group_type: group
+          admin_label: ''
+          operator: or
+          value: {  }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: field_test_target_id_op
+            label: 'Test (field_test)'
+            description: ''
+            use_operator: false
+            operator: field_test_target_id_reference_op
+            identifier: field_test_target_id
+            required: false
+            remember: false
+            multiple: true
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              administrator: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+          reduce_duplicates: false
+          sub_handler: 'default:node'
+          sub_handler_settings:
+            target_bundles:
+              article: article
+            sort:
+              field: title
+              direction: ASC
+            auto_create: false
+            auto_create_bundle: ''
+          widget: select
+          plugin_id: entity_reference
+        field_test_config_target_id_reference:
+          id: field_test_config_target_id_reference
+          table: node__field_test_config
+          field: field_test_config_target_id_reference
+          relationship: none
+          group_type: group
+          admin_label: ''
+          plugin_id: entity_reference
+          operator: or
+          value: { }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: field_test_config_target_id_reference_op
+            label: 'Test config (field_test_config) as a Reference filter'
+            description: ''
+            use_operator: false
+            operator: field_test_config_target_id_reference_op
+            operator_limit_selection: false
+            operator_list: { }
+            identifier: field_test_config_target_id_reference
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              content_editor: '0'
+              administrator: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: { }
+            group_items: { }
+          reduce_duplicates: false
+          sub_handler: 'default:node_type'
+          widget: select
+          sub_handler_settings:
+            target_bundles: null
+            auto_create: false
+        uid_reference:
+          id: uid_reference
+          table: node_field_data
+          field: uid_reference
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: uid
+          plugin_id: entity_reference
+          operator: or
+          value: { }
+          group: 1
+          exposed: true
+          expose:
+            operator_id: uid_reference_op
+            label: 'Authored by as a Reference filter'
+            description: ''
+            use_operator: false
+            operator: uid_reference_op
+            operator_limit_selection: false
+            operator_list: { }
+            identifier: uid_reference
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+              anonymous: '0'
+              content_editor: '0'
+              administrator: '0'
+            reduce: false
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: { }
+            group_items: { }
+          reduce_duplicates: false
+          sub_handler: 'default:user'
+          widget: select
+          sub_handler_settings:
+            target_bundles: null
+            sort:
+              field: _none
+              direction: ASC
+            auto_create: false
+            filter:
+              type: _none
+            include_anonymous: true
+      sorts:
+        created:
+          id: created
+          table: node_field_data
+          field: created
+          order: DESC
+          entity_type: node
+          entity_field: created
+          plugin_id: date
+          relationship: none
+          group_type: group
+          admin_label: ''
+          exposed: false
+          expose:
+            label: ''
+          granularity: second
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+      display_extenders: {  }
diff --git a/core/modules/views/tests/modules/views_test_entity_reference/config/install/views.view.test_entity_reference.yml b/core/modules/views/tests/modules/views_test_entity_reference/config/install/views.view.test_entity_reference.yml
new file mode 100644
index 0000000000..4b37d55d49
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_entity_reference/config/install/views.view.test_entity_reference.yml
@@ -0,0 +1,269 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - node
+    - user
+id: test_entity_reference
+label: 'Test Entity Reference'
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+display:
+  default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: 0
+    display_options:
+      fields:
+        title:
+          id: title
+          table: node_field_data
+          field: title
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: false
+            ellipsis: false
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+      pager:
+        type: mini
+        options:
+          offset: 0
+          items_per_page: 10
+          total_pages: null
+          id: 0
+          tags:
+            next: â€ºâ€º
+            previous: â€¹â€¹
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: tag
+        options: {  }
+      empty: {  }
+      sorts:
+        created:
+          id: created
+          table: node_field_data
+          field: created
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: created
+          plugin_id: date
+          order: DESC
+          expose:
+            label: ''
+            field_identifier: ''
+          exposed: false
+          granularity: second
+      arguments: {  }
+      filters:
+        status:
+          id: status
+          table: node_field_data
+          field: status
+          entity_type: node
+          entity_field: status
+          plugin_id: boolean
+          value: '1'
+          group: 1
+          expose:
+            operator: ''
+            operator_limit_selection: false
+            operator_list: {  }
+        type:
+          id: type
+          table: node_field_data
+          field: type
+          entity_type: node
+          entity_field: type
+          plugin_id: bundle
+          value:
+            article: article
+          expose:
+            operator_limit_selection: false
+            operator_list: {  }
+        title:
+          id: title
+          table: node_field_data
+          field: title
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: title
+          plugin_id: string
+          operator: '='
+          value: 'Article 0'
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            operator_limit_selection: false
+            operator_list: {  }
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+            placeholder: ''
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+      style:
+        type: default
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          uses_fields: false
+      row:
+        type: fields
+        options:
+          default_field_elements: true
+          inline: {  }
+          separator: ''
+          hide_empty: false
+      query:
+        type: views_query
+        options:
+          query_comment: ''
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_tags: {  }
+      relationships: {  }
+      header: {  }
+      footer: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url.query_args
+        - 'user.node_grants:view'
+        - user.permissions
+      tags: {  }
+  entity_reference:
+    id: entity_reference
+    display_title: 'Entity Reference'
+    display_plugin: entity_reference
+    position: 1
+    display_options:
+      style:
+        type: entity_reference
+        options:
+          search_fields:
+            title: title
+      row:
+        type: entity_reference
+        options:
+          default_field_elements: true
+          inline: {  }
+          separator: '-'
+          hide_empty: false
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - 'user.node_grants:view'
+        - user.permissions
+      tags: {  }
diff --git a/core/modules/views/tests/modules/views_test_entity_reference/views_test_entity_reference.info.yml b/core/modules/views/tests/modules/views_test_entity_reference/views_test_entity_reference.info.yml
new file mode 100644
index 0000000000..31f75a935a
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_entity_reference/views_test_entity_reference.info.yml
@@ -0,0 +1,7 @@
+name: 'Views Test Entity Reference'
+type: module
+description: 'Provides an entity reference view for use in a selection handler.'
+package: Testing
+version: VERSION
+dependencies:
+  - drupal:views
diff --git a/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php b/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php
index fd172ce627..718e64524e 100644
--- a/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php
+++ b/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php
@@ -56,6 +56,7 @@ class EntityViewsDataTest extends KernelTestBase {
     'field',
     'text',
     'filter',
+    'views',
   ];
 
   /**
diff --git a/core/modules/views/tests/src/Kernel/Handler/FilterEntityReferenceTest.php b/core/modules/views/tests/src/Kernel/Handler/FilterEntityReferenceTest.php
new file mode 100644
index 0000000000..82fce43b66
--- /dev/null
+++ b/core/modules/views/tests/src/Kernel/Handler/FilterEntityReferenceTest.php
@@ -0,0 +1,243 @@
+<?php
+
+namespace Drupal\Tests\views\Kernel\Handler;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
+use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
+use Drupal\Tests\node\Traits\NodeCreationTrait;
+use Drupal\Tests\user\Traits\UserCreationTrait;
+use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
+use Drupal\views\Plugin\views\filter\EntityReference;
+use Drupal\views\Tests\ViewTestData;
+use Drupal\views\Views;
+
+/**
+ * Tests the core Drupal\views\Plugin\views\filter\EntityReference handler.
+ *
+ * @group views
+ */
+class FilterEntityReferenceTest extends ViewsKernelTestBase {
+
+  use ContentTypeCreationTrait;
+  use EntityReferenceFieldCreationTrait;
+  use NodeCreationTrait;
+  use UserCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $testViews = ['test_filter_entity_reference'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'system',
+    'node',
+    'user',
+    'field',
+    'text',
+    'filter',
+    'views',
+  ];
+
+  /**
+   * Test host nodes containing the entity reference.
+   *
+   * @var \Drupal\node\NodeInterface[]
+   */
+  protected $hostNodes;
+
+  /**
+   * Test target nodes referenced by the entity reference.
+   *
+   * @var \Drupal\node\NodeInterface[]
+   */
+  protected $targetNodes;
+
+  /**
+   * First test user as node author.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $user1;
+
+  /**
+   * Second test user as node author.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $user2;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp($import_test_views = TRUE): void {
+    parent::setUp(FALSE);
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('user');
+    $this->installConfig(['node', 'user', 'filter']);
+
+    ViewTestData::createTestViews(static::class, ['views_test_config']);
+    // Create two node types.
+    $this->createContentType(['type' => 'page']);
+    $this->createContentType(['type' => 'article']);
+
+    // Add an entity reference field to the page type referencing the article
+    // type.
+    $selection_handler_settings = [
+      'target_bundles' => [
+        'article' => 'article',
+      ],
+    ];
+    $this->createEntityReferenceField('node', 'page', 'field_test', 'Test reference', 'node', $selection_handler = 'default', $selection_handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
+    // Create user 1.
+    $this->user1 = $this->createUser();
+    $this->user2 = $this->createUser();
+
+    // Create target nodes to be referenced.
+    foreach (range(0, 5) as $count) {
+      $this->targetNodes[$count] = $this->createNode([
+        'type' => 'article',
+        'title' => 'Article ' . $count,
+        'status' => 1,
+        'uid' => $this->user1,
+      ]);
+    }
+
+    // Create a page referencing Article 0 and Article 1.
+    $this->hostNodes[0] = $this->createNode([
+      'type' => 'page',
+      'title' => 'Page 0',
+      'status' => 1,
+      'created' => time(),
+      'field_test' => [
+        $this->targetNodes[0]->id(),
+        $this->targetNodes[1]->id(),
+      ],
+      'uid' => $this->user2,
+    ]);
+
+    // Create a page referencing Article 1, Article 2, and Article 3.
+    $this->hostNodes[1] = $this->createNode([
+      'type' => 'page',
+      'title' => 'Page 1',
+      'status' => 1,
+      'created' => time() - 100,
+      'field_test' => [
+        $this->targetNodes[1]->id(),
+        $this->targetNodes[2]->id(),
+        $this->targetNodes[3]->id(),
+      ],
+      'uid' => $this->user2,
+    ]);
+
+    // Create a page referencing nothing.
+    $this->hostNodes[2] = $this->createNode([
+      'type' => 'page',
+      'title' => 'Page 2',
+      'status' => 1,
+      'created' => time() - 200,
+      'uid' => $this->user2,
+    ]);
+  }
+
+  /**
+   * Tests that results are successfully filtered by the select list widget.
+   */
+  public function testViewEntityReferenceAsSelectList() {
+    $view = Views::getView('test_filter_entity_reference');
+    $view->setDisplay();
+    $view->preExecute([]);
+    $view->setExposedInput([
+      'field_test_target_id' => [$this->targetNodes[0]->id()],
+    ]);
+    $this->executeView($view);
+
+    // Expect to have only Page 0, with Article 0 referenced.
+    $expected = [
+      ['title' => 'Page 0'],
+    ];
+    $this->assertIdenticalResultset($view, $expected, [
+      'title' => 'title',
+    ]);
+
+    // Change to both Article 0 and Article 3.
+    $view = Views::getView('test_filter_entity_reference');
+    $view->setDisplay();
+    $view->setExposedInput([
+      'field_test_target_id' => [
+        $this->targetNodes[0]->id(),
+        $this->targetNodes[3]->id(),
+      ],
+    ]);
+    $this->executeView($view);
+
+    // Expect to have Page 0 and 1, with Article 0 and 3 referenced.
+    $expected = [
+      ['title' => 'Page 0'],
+      ['title' => 'Page 1'],
+    ];
+    $this->assertIdenticalResultset($view, $expected, [
+      'title' => 'title',
+    ]);
+
+    // Change to filtering by user 1 base field.
+    $view = Views::getView('test_filter_entity_reference');
+    $view->setDisplay();
+    $view->setExposedInput([
+      'uid_reference' => $this->user1->id(),
+    ]);
+    $this->executeView($view);
+
+    // Change to filtering by user 1 base field.
+    $view = Views::getView('test_filter_entity_reference');
+    $view->setDisplay();
+    $view->setExposedInput([
+      'uid_reference' => $this->user2->id(),
+    ]);
+    $this->executeView($view);
+
+    // Expect to have only the articles referenced.
+    $expected = [
+      ['title' => 'Page 0'],
+      ['title' => 'Page 1'],
+      ['title' => 'Page 2'],
+    ];
+    $this->assertIdenticalResultset($view, $expected, [
+      'title' => 'title',
+    ]);
+  }
+
+  /**
+   * Tests that results are successfully filtered by the autocomplete widget.
+   */
+  public function testViewEntityReferenceAsAutocomplete() {
+
+    // Change the widget to autocomplete.
+    $view = Views::getView('test_filter_entity_reference');
+    $view->setDisplay();
+    $filters = $view->displayHandlers->get('default')->getOption('filters');
+    $filters['field_test_target_id']['widget'] = EntityReference::WIDGET_AUTOCOMPLETE;
+    $view->displayHandlers->get('default')->overrideOption('filters', $filters);
+    $view->setExposedInput([
+      'field_test_target_id' => [
+        ['target_id' => $this->targetNodes[0]->id()],
+        ['target_id' => $this->targetNodes[3]->id()],
+      ],
+    ]);
+    $this->executeView($view);
+
+    // Expect to have Page 0 and 1, with Article 0 and 3 referenced.
+    $expected = [
+      ['title' => 'Page 0'],
+      ['title' => 'Page 1'],
+    ];
+    $this->assertIdenticalResultset($view, $expected, [
+      'title' => 'title',
+    ]);
+  }
+
+}
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 90cc66698f..1c8cc7c2be 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -820,3 +820,38 @@ function views_view_presave(ViewEntityInterface $view) {
   $config_updater = \Drupal::classResolver(ViewsConfigUpdater::class);
   $config_updater->updateAll($view);
 }
+
+/**
+ * Add an Entity Reference filter for a given Entity Reference Views Table Data.
+ *
+ * Helper function, multiple usage.
+ *
+ * @param string $field_name
+ *   The name of the field to add new  entity reference filter for.
+ * @param $field_table_data
+ *   A Views table data array for an entity reference field to add the new
+ *   Entity Reference filter data.
+ */
+function _views_add_entity_reference_filter_data(string $field_name, array &$field_table_data) {
+  // Copy the field data.
+  $entity_reference = $field_table_data[$field_name];
+  if (isset($entity_reference['filter']) && $entity_reference['filter']['id'] != 'entity_reference') {
+    // Remove the handler options for all but the filter handler.
+    $handler_types = Views::getHandlerTypes();
+    foreach (array_keys($handler_types) as $handler_type) {
+      unset($entity_reference[$handler_type]);
+    }
+
+    // Build the views filter data.
+    $entity_reference['filter'] = $field_table_data[$field_name]['filter'];
+    $entity_reference['filter']['id'] = 'entity_reference';
+    $entity_reference['title'] = $entity_reference['title'] . ' ' . t('as a Reference filter');
+    if (!isset($entity_reference['filter']['field'])) {
+      $entity_reference['filter']['field'] = $field_name;
+    }
+
+    // Create separate views data to allow use of the entity_reference
+    // filter.
+    $field_table_data[$field_name . '_reference'] = $entity_reference;
+  }
+}
diff --git a/core/modules/views/views.views.inc b/core/modules/views/views.views.inc
index ebde44706b..426149f21c 100644
--- a/core/modules/views/views.views.inc
+++ b/core/modules/views/views.views.inc
@@ -767,10 +767,11 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora
 /**
  * Implements hook_field_views_data().
  *
- * The function implements the hook on behalf of 'core' because it adds a
- * relationship and a reverse relationship to entity_reference field type, which
- * is provided by core. This function also provides an argument plugin for
- * entity_reference fields that handles title token replacement.
+ * The function implements the hook in behalf of 'core' because it updates
+ * filters to use the entity_reference handler, adds a relationship and a
+ * reverse relationship to entity_reference field type, which is provided by
+ * core. This function also provides an argument plugin for entity_reference
+ * fields that handles title token replacement.
  */
 function core_field_views_data(FieldStorageConfigInterface $field_storage) {
   $data = views_field_default_views_data($field_storage);
@@ -795,6 +796,17 @@ function core_field_views_data(FieldStorageConfigInterface $field_storage) {
     $field_name = $field_storage->getName();
 
     if ($target_entity_type instanceof ContentEntityTypeInterface) {
+      foreach ($table_data as $table_field_name => $table_field_data) {
+        if (isset($table_field_data['filter']) && $table_field_name != 'delta') {
+          // Create separate views data to allow use of the entity_reference
+          // filter. Numeric filter should still be available for use.
+          $entity_reference = $data[$table_name][$table_field_name];
+          $entity_reference['filter']['id'] = 'entity_reference';
+          $entity_reference['title'] = $entity_reference['title'] . ' ' . t('as a Reference filter');
+          $data[$table_name][$table_field_name . '_reference'] = $entity_reference;
+        }
+      }
+
       // Provide a relationship for the entity type with the entity reference
       // field.
       $args = [
diff --git a/core/modules/views_ui/tests/src/Functional/FilterEntityReferenceWebTest.php b/core/modules/views_ui/tests/src/Functional/FilterEntityReferenceWebTest.php
new file mode 100644
index 0000000000..6be49405cf
--- /dev/null
+++ b/core/modules/views_ui/tests/src/Functional/FilterEntityReferenceWebTest.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Drupal\Tests\views_ui\Functional;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Component\Render\FormattableMarkup;
+use Drupal\Tests\views_ui\Traits\FilterEntityReferenceTrait;
+
+/**
+ * Tests the entity reference filter UI.
+ *
+ * @group views_ui
+ * @see \Drupal\views\Plugin\views\filter\EntityReference
+ */
+class FilterEntityReferenceWebTest extends UITestBase {
+
+  use FilterEntityReferenceTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $testViews = ['test_filter_entity_reference'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp($import_test_views = TRUE, $modules = []): void {
+    parent::setUp($import_test_views);
+    $this->setUpEntityTypes();
+  }
+
+  /**
+   * Tests the filter UI.
+   */
+  public function testFilterUi(): void {
+    $this->drupalGet('admin/structure/views/nojs/handler/test_filter_entity_reference/default/filter/field_test_target_id');
+
+    $options = $this->getUiOptions();
+    // Should be sorted by title ASC.
+    uasort($this->targetEntities, function (EntityInterface $a, EntityInterface $b) {
+      return strnatcasecmp($a->getTitle(), $b->getTitle());
+    });
+    $i = 0;
+    foreach ($this->targetEntities as $id => $entity) {
+      $this->assertEquals($options[$i]['label'], $entity->label(), new FormattableMarkup('Expected target entity label found for option :option', [':option' => $i]));
+      $i++;
+    }
+
+    // Change the sort field and direction.
+    $this->drupalGet('admin/structure/views/nojs/handler-extra/test_filter_entity_reference/default/filter/field_test_target_id');
+    $edit = [
+      'options[reference_default:node][sort][field]' => 'nid',
+      'options[reference_default:node][sort][direction]' => 'DESC',
+    ];
+    $this->submitForm($edit, 'Apply');
+
+    $this->drupalGet('admin/structure/views/nojs/handler/test_filter_entity_reference/default/filter/field_test_target_id');
+    // Items should now be in reverse id order.
+    krsort($this->targetEntities);
+    $options = $this->getUiOptions();
+    $i = 0;
+    foreach ($this->targetEntities as $id => $entity) {
+      $this->assertEquals($options[$i]['label'], $entity->label(), new FormattableMarkup('Expected target entity label found for option :option', [':option' => $i]));
+      $i++;
+    }
+
+    // Change bundle types.
+    $this->drupalGet('admin/structure/views/nojs/handler-extra/test_filter_entity_reference/default/filter/field_test_target_id');
+    $edit = [
+      "options[reference_default:node][target_bundles][{$this->hostEntityType->id()}]" => TRUE,
+      "options[reference_default:node][target_bundles][{$this->targetEntityType->id()}]" => TRUE,
+    ];
+    $this->submitForm($edit, 'Apply');
+
+    $this->drupalGet('admin/structure/views/nojs/handler/test_filter_entity_reference/default/filter/field_test_target_id');
+    $options = $this->getUiOptions();
+    $i = 0;
+    foreach ($this->hostEntities + $this->targetEntities as $id => $entity) {
+      $this->assertEquals($options[$i]['label'], $entity->label(), new FormattableMarkup('Expected target entity label found for option :option', [':option' => $i]));
+      $i++;
+    }
+  }
+
+  /**
+   * Helper method to parse options from the UI.
+   *
+   * @return array
+   *   Array of keyed arrays containing the id and label of each option.
+   */
+  protected function getUiOptions() {
+    /** @var \Behat\Mink\Element\TraversableElement[] $result */
+    $result = $this->xpath('//select[@name="options[value][]"]/option');
+    $this->assertNotEmpty($result, 'Options found');
+
+    $options = [];
+    foreach ($result as $option) {
+      $options[] = [
+        'id' => (int) $option->getValue(),
+        'label' => (string) $option->getText(),
+      ];
+    }
+
+    return $options;
+  }
+
+  /**
+   * Tests the filter UI for config reference.
+   */
+  public function testFilterConfigUi(): void {
+    $this->drupalGet('admin/structure/views/nojs/handler/test_filter_entity_reference/default/filter/field_test_config_target_id_reference');
+
+    $options = $this->getUiOptions();
+    // We should the content types defined as options.
+    $this->assertEquals(['article', 'page'], array_column($options, 'label'));
+  }
+
+}
diff --git a/core/modules/views_ui/tests/src/FunctionalJavascript/FilterEntityReferenceTest.php b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterEntityReferenceTest.php
new file mode 100644
index 0000000000..a77c7e8f2f
--- /dev/null
+++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterEntityReferenceTest.php
@@ -0,0 +1,268 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\views_ui\FunctionalJavascript;
+
+use Drupal\Core\Url;
+use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+use Drupal\Tests\views_ui\Traits\FilterEntityReferenceTrait;
+
+/**
+ * Tests views creation wizard.
+ *
+ * @group views_ui
+ * @see \Drupal\views\Plugin\views\filter\EntityReference
+ */
+class FilterEntityReferenceTest extends WebDriverTestBase {
+
+  use FilterEntityReferenceTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'node',
+    'views',
+    'views_ui',
+    'views_test_entity_reference',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * Views used by this test.
+   *
+   * @var array
+   */
+  public static $testViews = ['test_entity_reference'];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(): void {
+    parent::setUp();
+
+    $admin_user = $this->drupalCreateUser([
+      'administer views',
+    ]);
+    $this->drupalLogin($admin_user);
+
+    $this->setUpEntityTypes();
+  }
+
+  /**
+   * Tests end to end creation of a Content Entity Reference filter.
+   */
+  public function testAddEntityReferenceFieldWithDefaultSelectionHandler() {
+    $this->drupalGet('admin/structure/views/view/content');
+    $assert = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    // Open the dialog.
+    $page->clickLink('views-add-filter');
+
+    // Wait for the popup to open and the search field to be available.
+    $assert->waitForField('override[controls][options_search]');
+
+    // Test that the both entity_reference and numeric options are visible.
+    $this->assertTrue($page->findField('name[node__field_test.field_test_target_id]')
+      ->isVisible());
+    $this->assertTrue($page->findField('name[node__field_test.field_test_target_id_reference]')
+      ->isVisible());
+    $page->findField('name[node__field_test.field_test_target_id_reference]')
+      ->click();
+    $this->assertTrue($page->find('css', 'button.button.button--primary.form-submit.ui-button')
+      ->isVisible());
+    $page->find('css', 'button.button.button--primary.form-submit.ui-button')
+      ->click();
+
+    // Wait for the selection handler to show up.
+    $assert->waitForField('options[sub_handler]');
+    $page->selectFieldOption('options[sub_handler]', 'default:node');
+
+    // Check that that default handler target bundles are available.
+    $this->assertTrue($page->findField('options[reference_default:node][target_bundles][article]')
+      ->isVisible());
+    $this->assertTrue($page->findField('options[reference_default:node][target_bundles][page]')
+      ->isVisible());
+    $this->assertTrue($page->findField('options[widget]')->isVisible());
+
+    // Ensure that disabled form elements from selection handler do not show up
+    // @see \Drupal\views\Plugin\views\filter\EntityReference method
+    // buildExtraOptionsForm.
+    $this->assertFalse($page->hasField('options[reference_default:node][target_bundles_update]'));
+    $this->assertFalse($page->hasField('options[reference_default:node][auto_create]'));
+    $this->assertFalse($page->hasField('options[reference_default:node][auto_create_bundle]'));
+
+    // Choose the default handler using the select widget with article type
+    // checked.
+    $page->checkField('options[reference_default:node][target_bundles][article]');
+    $page->selectFieldOption('options[widget]', 'select');
+    $this->assertSame($page->findField('options[widget]')
+      ->getValue(), 'select');
+    $page->find('xpath', "//*[contains(text(), 'Apply and continue')]")
+      ->press();
+
+    // Test the exposed filter options show up correctly.
+    // Test the exposed filter options show up correctly.
+    $assert->waitForField('options[expose_button][checkbox][checkbox]');
+    $page->findField('options[expose_button][checkbox][checkbox]')->click();
+    $this->assertTrue($page->hasCheckedField('options[expose_button][checkbox][checkbox]'));
+
+    // Check the exposed filters multiple option.
+    $assert->waitForField('options[expose][multiple]');
+    $page->findField('options[expose][multiple]')->click();
+    $this->assertTrue($page->hasCheckedField('options[expose][multiple]'));
+    $page->find('css', '.ui-dialog .ui-dialog-buttonpane')->pressButton('Apply');
+    $assert->waitForElementRemoved('css', '.ui-dialog');
+
+    // Wait for the Views Preview to show up with the new reference field.
+    $assert->waitForField('field_test_config_target_id_reference[]');
+    $this->assertTrue($page->findField('field_test_target_id_reference[]')
+      ->isVisible());
+    $this->assertTrue($page->find('css', 'select[name="field_test_target_id_reference[]"]')
+      ->hasAttribute('multiple'));
+
+    // Opening the settings form and change the handler to use an Entity
+    // Reference view.
+    // @see views.view.test_entity_reference.yml
+    $base_url = Url::fromRoute('entity.view.collection')->toString();
+    $url = $base_url . '/nojs/handler-extra/content/page_1/filter/field_test_target_id_reference';
+    $extra_settings_selector = 'a[href="' . $url . '"]';
+    $element = $this->assertSession()->waitForElementVisible('css', $extra_settings_selector);
+    $this->assertNotNull($element);
+    $element->click();
+    $assert->waitForField('options[sub_handler]');
+    $page->selectFieldOption('options[sub_handler]', 'views');
+    $page->selectFieldOption('options[reference_views][view][view_and_display]', 'test_entity_reference:entity_reference');
+    $page->find('xpath', "//*[contains(text(), 'Apply')]")
+      ->press();
+    $assert->assertWaitOnAjaxRequest();
+
+    // The Views Reference filter has a title Filter to a single result, so
+    // ensure only that result is available as an option.
+    $assert->waitForElementRemoved('css', '.ui-dialog');
+
+    $this->assertCount(1, $page->findAll('css', 'select[name="field_test_target_id_reference[]"] option'));
+
+    // Change to an autocomplete filter.
+    // Opening the settings form and change the handler to use an Entity
+    // Reference view.
+    // @see views.view.test_entity_reference.yml
+    $page->find('css', $extra_settings_selector)
+      ->click();
+    $assert->waitForElementVisible('named', [
+      'radio',
+      'options[widget]',
+    ]);
+    $page->selectFieldOption('options[widget]', 'autocomplete');
+    $this->assertSame($page->findField('options[widget]')
+      ->getValue(), 'autocomplete');
+    $this->getSession()
+      ->getPage()
+      ->find('xpath', "//*[contains(text(), 'Apply')]")
+      ->press();
+
+    // Check that it is now an autocomplete.
+    $assert->waitForField('field_test_target_id_reference');
+    $page = $this->getSession()->getPage();
+    $this->assertTrue($page->findField('field_test_target_id_reference')
+      ->isVisible());
+    $this->assertTrue($page->find('css', 'input[name="field_test_target_id_reference"]')
+      ->hasAttribute('data-autocomplete-path'));
+  }
+
+  /**
+   * Tests end to end creation of a Config Entity Reference filter.
+   */
+  public function testAddConfigEntityReferenceFieldWithDefaultSelectionHandler() {
+    $this->drupalGet('admin/structure/views/view/content');
+    $assert = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    // Open the dialog.
+
+    // Open the 'Add filter dialog'.
+    $page->clickLink('views-add-filter');
+
+    // Wait for the popup to open and the search field to be available.
+    $assert->waitForField('override[controls][group]');
+
+    // Test that the both entity_reference and numeric options are visible.
+    $this->assertTrue($page->findField('name[node__field_test_config.field_test_config_target_id]')
+      ->isVisible());
+    $this->assertTrue($page->findField('name[node__field_test_config.field_test_config_target_id_reference]')
+      ->isVisible());
+    $page->findField('name[node__field_test_config.field_test_config_target_id_reference]')
+      ->click();
+    $this->assertTrue($page->find('css', 'button.button.button--primary.form-submit.ui-button')
+      ->isVisible());
+    $this->htmlOutput($page->getHtml());
+    $page->find('css', 'button.button.button--primary.form-submit.ui-button')
+      ->click();
+
+    // Wait for the selection handler to show up.
+    $assert->waitForField('options[sub_handler]');
+
+    $page->selectFieldOption('options[sub_handler]', 'default:node_type');
+
+    // Choose the default handler using the select widget with article type
+    // checked.
+    $page->selectFieldOption('options[widget]', 'select');
+    $this->assertSame($page->findField('options[widget]')
+      ->getValue(), 'select');
+    $page->find('xpath', "//*[contains(text(), 'Apply and continue')]")
+      ->press();
+
+    // Test the exposed filter options show up correctly.
+    $assert->waitForField('options[expose_button][checkbox][checkbox]');
+    $page->findField('options[expose_button][checkbox][checkbox]')->click();
+    $this->assertTrue($page->hasCheckedField('options[expose_button][checkbox][checkbox]'));
+
+    // Check the exposed filters multiple option.
+    $assert->waitForField('options[expose][multiple]');
+    $page->findField('options[expose][multiple]')->click();
+    $this->assertTrue($page->hasCheckedField('options[expose][multiple]'));
+    $page->find('css', '.ui-dialog .ui-dialog-buttonpane')->pressButton('Apply');
+    $assert->waitForElementRemoved('css', '.ui-dialog');
+
+    // Wait for the Views Preview to show up with the new reference field.
+    $assert->waitForField('field_test_config_target_id_reference[]');
+    $this->assertTrue($page->findField('field_test_config_target_id_reference[]')
+      ->isVisible());
+    $this->assertTrue($page->find('css', 'select[name="field_test_config_target_id_reference[]"]')
+      ->hasAttribute('multiple'));
+
+    // Check references config options.
+    $options = $page->findAll('css', 'select[name="field_test_config_target_id_reference[]"] option');
+    $this->assertCount(2, $options);
+    $this->assertSame('article', $options[0]->getValue());
+    $this->assertSame('page', $options[1]->getValue());
+
+    $base_url = Url::fromRoute('entity.view.collection')->toString();
+    $url = $base_url . '/nojs/handler-extra/content/page_1/filter/field_test_config_target_id_reference';
+    $extra_settings_selector = 'a[href="' . $url . '"]';
+
+    // Change to an autocomplete filter.
+    $page->find('css', $extra_settings_selector)
+      ->click();
+    $assert->waitForField('options[widget]');
+    $page->selectFieldOption('options[widget]', 'autocomplete');
+    $this->assertSame($page->findField('options[widget]')
+      ->getValue(), 'autocomplete');
+    $page->find('css', '.ui-dialog .ui-dialog-buttonpane')->pressButton('Apply');
+    $this->assertSession()->assertWaitOnAjaxRequest();
+
+    // Check that it is now an autocomplete input.
+    $assert->waitForField('field_test_config_target_id_reference');
+    $this->assertTrue($page->findField('field_test_config_target_id_reference')
+      ->isVisible());
+    $this->assertTrue($page->find('css', 'input[name="field_test_config_target_id_reference"]')
+      ->hasAttribute('data-autocomplete-path'));
+  }
+
+}
diff --git a/core/modules/views_ui/tests/src/Traits/FilterEntityReferenceTrait.php b/core/modules/views_ui/tests/src/Traits/FilterEntityReferenceTrait.php
new file mode 100644
index 0000000000..8db9d96820
--- /dev/null
+++ b/core/modules/views_ui/tests/src/Traits/FilterEntityReferenceTrait.php
@@ -0,0 +1,135 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\views_ui\Traits;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
+use Drupal\Tests\node\Traits\NodeCreationTrait;
+
+/**
+ * Sets up the entity types and relationships for entity reference tests.
+ *
+ * This trait is meant to be used only by test classes.
+ */
+trait FilterEntityReferenceTrait {
+
+  use ContentTypeCreationTrait {
+    createContentType as drupalCreateContentType;
+  }
+  use NodeCreationTrait {
+    getNodeByTitle as drupalGetNodeByTitle;
+    createNode as drupalCreateNode;
+  }
+
+  /**
+   * The host Entity type to add the entity reference field to.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface
+   */
+  protected $hostEntityType;
+
+  /**
+   * The Entity type to be referenced by the host Entity type.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface
+   */
+  protected $targetEntityType;
+
+  /**
+   * Entities to be used as reference targets.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface[]
+   */
+  protected $targetEntities;
+
+  /**
+   * Host entities which contain the reference fields to the target entities.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface[]
+   */
+  protected $hostEntities;
+
+  /**
+   * Sets up the entity types and relationships.
+   */
+  protected function setUpEntityTypes() {
+
+    // Create an entity type, and a referenceable type. Since these are coded
+    // into the test view, they are not randomly named.
+    $this->hostEntityType = $this->drupalCreateContentType(['type' => 'page']);
+    $this->targetEntityType = $this->drupalCreateContentType(['type' => 'article']);
+
+    $field_storage = FieldStorageConfig::create([
+      'entity_type' => 'node',
+      'field_name' => 'field_test',
+      'type' => 'entity_reference',
+      'settings' => [
+        'target_type' => 'node',
+      ],
+      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
+    ]);
+    $field_storage->save();
+
+    $field = FieldConfig::create([
+      'entity_type' => 'node',
+      'field_name' => 'field_test',
+      'bundle' => $this->hostEntityType->id(),
+      'settings' => [
+        'handler' => 'default',
+        'handler_settings' => [
+          'target_bundles' => [
+            $this->targetEntityType->id() => $this->targetEntityType->label(),
+          ],
+        ],
+      ],
+    ]);
+    $field->save();
+
+    // Create 10 nodes for use as target entities.
+    for ($i = 0; $i < 10; $i++) {
+      $node = $this->drupalCreateNode([
+        'type' => $this->targetEntityType->id(),
+        'title' => ucfirst($this->targetEntityType->id()) . ' ' . $i,
+      ]);
+      $this->targetEntities[$node->id()] = $node;
+    }
+
+    // Create 1 host entity to reference target entities from.
+    $node = $this->drupalCreateNode([
+      'type' => $this->hostEntityType->id(),
+      'title' => ucfirst($this->hostEntityType->id()) . ' 0',
+    ]);
+    $this->hostEntities = [
+      $node->id() => $node,
+    ];
+
+    $field_storage = FieldStorageConfig::create([
+      'entity_type' => 'node',
+      'field_name' => 'field_test_config',
+      'type' => 'entity_reference',
+      'settings' => [
+        'target_type' => 'node_type',
+      ],
+      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
+    ]);
+    $field_storage->save();
+
+    $field = FieldConfig::create([
+      'entity_type' => 'node',
+      'field_name' => 'field_test_config',
+      'bundle' => $this->hostEntityType->id(),
+      'settings' => [
+        'handler' => 'default',
+        'handler_settings' => [
+          'sort' => ['field' => '_none'],
+        ],
+      ],
+    ]);
+    $field->save();
+  }
+
+}
