Skip to main content
ocean waves

Blog Post

Drupal 8: How to Reference a Views' Block Display from a Field

In Drupal 7, if you wanted to reference a view display from a node field, you had to use a module such as Viewfield. In Drupal 8, this can be done with Drupal core alone by using the built in entity reference to reference a block instance created from the view.

Step 1: Create a hidden region in your theme.

1. Open your THEMENAME.info.yml file.
2. Find the section for "regions:"
3. Add a new line: hidden: 'Hidden region for referenced blocks'

Hidden region

4. Save and clear the cache.
 

Step 2: Create a view with a block display.

1. Go to admin/structure/views/add
2. Create your view with a block display.

Block Display

3. Do any additional tweaking you'd like and save the view.
 

Step 3: Place an instance of the block in the hidden region.

1. Go to admin/structure/block
2. Find the hidden region you just added in step 1.

Hidden region

3. Click "Place block".
4. Find your Views block.
5. Click "Place block".
6. Configure as desired and save.

Reference block
Hidden region
 

Step 4: Create a reference field.

1. Go to the field admin of your content type at admin/structure/types/manage/TYPE/fields.
2. Click "Add field".
3. In the "Add a new field" dropdown, choose "Other" under "Reference".

Reference field

4. Label the field and save.
5. Under "Type of item to reference" choose "Block" under "Configuration" and save.

Reference field

6. Configure as desired. Leave "Reference method" set to "Default".

Reference field
7. Optionally set a block as the default:

a. If you are only going to ever reference one view from this field and you want it automatically added, you can set it as the default value.

b. If you would like to be able to select from multiple blocks, leave the default value blank and the user can choose when entering content. The default format of the field is autocomplete but this can be changed to a dropdown in admin/structure/types/manage/TYPE/form-display to make the choices more obvious.

8. Save the field.
 

Step 5: Add the block to your content.

1. Add a new item of the content type from step 4 at /node/add/TYPE.
2. You should see your new field. If you set the default in Step 4, the view will automatically be filled in.

Content block
 

(Optional) Step 6: Alter code to limit the field.

If you are allowing the user to choose the view when entering content, you'll notice that the list is cluttered because it is showing _all_ the blocks on the site.

Reference field
 

To make things cleaner, you can limit the list to just blocks placed in the hidden region with this:

1. If you don't already have one, create a custom module for site wide alterations.
2. Add the following directory structure under the root directory of the module: src/Plugin/EntityReferenceSelection.

Directory Structure

3. In EntityReferenceSelection, add a file named BlockSelection.php. (The filename can be changed; just be sure it matches the class name.)
4. In this file, add the following code. Be sure to replace "MODULE_NAME_HERE", "YOUR_SITE_THEME". Also change "hidden" if you chose a different name for the region.
 

<?php

namespace Drupal\MODULE_NAME_HERE\Plugin\EntityReferenceSelection;

use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
use Drupal\Component\Utility\Html;

/**
 * Filters the block listing for an entity reference field.
 *
 * @EntityReferenceSelection(
 *   id = "blocks",
 *   label = @Translation("Blocks: Filter by blocks in hidden region"),
 *   entity_types = {"block"},
 *   group = "blocks",
 *   weight = 1
 * )
 */
class BlockSelection extends DefaultSelection {

  /**
   * {@inheritdoc}
   */
  public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
    $target_type = $this->configuration['target_type'];

    $query = $this->buildEntityQuery($match, $match_operator);
    if ($limit > 0) {
      $query->range(0, $limit);
    }

    $result = $query->execute();

    if (empty($result)) {
      return array();
    }

    $options = array();
    $entities = $this->entityManager->getStorage($target_type)->loadMultiple($result);
    foreach ($entities as $entity_id => $entity) {
      $block_theme = $entity->getTheme();
      $block_region = $entity->getRegion();

      // Only add blocks that are in the hidden region of the main theme.
      if ($block_theme == 'YOUR_SITE_THEME' && $block_region == 'hidden') {
        $bundle = $entity->bundle();
        $options[$bundle][$entity_id] = Html::escape($this->entityManager->getTranslationFromContext($entity)
          ->label());
      }
    }

    // Sort the options alphabetically.
    asort($options['block']);
    return $options;
  }

}

5. Save the file and clear the cache.
6. Edit the field you added in step 4 above.
7. Change the reference method to "Blocks: Filter by blocks in hidden region" and save.

Reference Type

8. Add a new item of the content type from step 4 at /node/add/TYPE.
9. The field will now be restricted to only showing blocks in the "hidden" region.

Hidden Region
 

As you can see, with just Drupal core you can give your content editors the flexibility to choose from different sets of data (views) while creating a node. For even more flexibility, add the Paragraphs module and add your block reference field to a paragraph type. If you then assign the field on the content type to reference paragraphs, you can set it up so your editor can choose either a premade list (one of the views) or curate the list themselves by choosing a paragraph that allows them to pick individual items of content. With a single content type, your editors can create a variety of different pages depending on their needs.
 

Additional Resources
Migration With Custom Values in Drupal 8 | Blog
Migrating Content References in Drupal 8 | Blog
5 Drupal 8 Development Tips | Video

Thumbnail

Meet team member, Michelle Cox

Michelle started using Drupal in 2005 with the 4.6 release. She spent the next seven years actively participating in the community by writing and maintaining three contributed modules, assisting in...

Learn more about Michelle >