Thumbnail

Views Entity Reference Filter

Thumbnail

Campbell Tilley

|

So you've got a View with an exposed filter on an Entity Reference field? And the exposed filter is only allowing you to pass through the Entity ID? I had the same problem... but lucky for you, I've found a solution and I'm sharing it with you!

By default, in Views, an exposed Entity Reference field filter can only be filtered by their Entity ID. I thought this was a very odd decision because visitors will normally only have access to a title and not the ID.

The Views Entity Reference Filter module is a very quick solution to this problem. Instead of using the Entity ID, it exposes a select list containing the title of the Entities.

  1. Install the module on your site
  2. Navigate to your view and add a filter
  3. Find the field you want to filter on and select the field with the suffix (VERF selector)
  4. Expose this filter to allow visitors to use it

Out of the box, there are two issues with this filter that I have uncovered (Note that these issues are relevant at the time of me writing this article and could be fixed by the time you install the module).

The first issue I found is that if you try to limit the allowed options in the filter settings, an error will be thrown and you can't save your view. If you do come across this issue while trying to configure your view, here's the patch to fix it - https://www.drupal.org/files/issues/2018-10-18/invalidargumentexception-2871758-8.patch

The second issue is that the filter shows all options in the select list, whether the options has been used in the view or not. When you have an entity with 100+ items and only 5 of those items being used in the view, the select list becomes more of a hassle than it's worth. I wanted my select list to only show the 5 entity items that were being used, as well as an 'All' option.

To solve this issue, I created a hook_form_FORM_ID_form_alter() in my module.module file. Below is the code for the function. Note it will need to be tweaked to fit your use case.

/**
 * Implements hook_form_FORM_ID_form_alter().
 */
function module_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form['#id'] == 'views-exposed-form-view-name-page-1') {

    if (array_key_exists('field_name_target_id', $form)) {

      // Rewrite the default 'All' option
      if (!empty($form['field_name_target_id']['#options']['All'])) {
        $option_default = ['All' => t('- Any -')];
      }

      $options = $form['field_name_target_id']['#options'];

      // Ensure that only terms that are used in the view
      // are displayed in the filter
      $connection = Database::getConnection();
      $query = $connection->select('node__field_name', 'vocabulary');
      $query->join('node_field_data', 'n', 'n.nid = vocabulary.entity_id');
      $query->fields('vocabulary', ['field_name_target_id']);
      $query->fields('n', ['status']);
      $query->condition('vocabulary.bundle', 'nodebundle');
      $query->condition('n.status', 1);
      $data = $query->distinct()->execute();

      $results = array_flip($data->fetchAll(\PDO::FETCH_COLUMN, 'field_name_target_id'));
      $options = array_intersect_key($options, $results);

      // Rebuild the option select with the term values and the all option
      $form['field_name_target_id']['#options'] = $option_default + $options;
    }
  }
}

 

Add new comment

The content of this field is kept private and will not be shown publicly.

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.

Comments

  • Allowed HTML tags: <em> <strong> <cite> <blockquote cite> <ul type> <ol start type> <li> <dl> <dt> <dd> <p>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
  • Use [gist:#####] where ##### is your gist number to embed the gist
    You may also include a specific file within a multi-file gist with [gist:####:my_file].

Spread the word