How to add a View block directly to a template in Drupal 8

The problem

You have a home, section or landing page and you need to add blocks from the Views module. You can use modules like Context, Panels or the new Drupal 8 Layouts to add blocks, including View blocks. But sometimes you just want to do this programmatically in the theme without messing around with another module and all the overhead that includes.

A solution

There are three parts to this solution

  1. Use the views_embed_view() with the view and display name as arguments to embed the view
  2. Assign the result to a variable in a pre process function
  3. Render that variable in the template

An example

On the home page of a website, you need to add a Feature article block which displays the latest article that has been flagged by an editor as “featured”. You already have a view for this called “content_list” and a block display called “block_1”. You want to display the featured article block on the homepage only.

Because this is for the homepage only, you can create a template called function page--front.html.twig.

In the .theme file for your theme, create an implementation of hook_preprocess_page().

/**
 * Implements hook_preprocess_page() for page.html.twig.
 */
function themename_preprocess_page__front(array &$variables) {

}

Replace themename with the name of your theme. This preprocess function allows you to pass variables to the page--front.html.twig template.

Next, define a new variable called $variables['featured'] and assign it the views_embed_view() function:

/**
 * Implements hook_preprocess_page() for page.html.twig.
 */
function themename_preprocess_page__front(array &$variables) {
  $variables['featured'] = views_embed_view('content_list', 'block_1');
}

And then in the page--front.html.twig template, you can render the featured variable with:

{{ featured }}

The rest of the page--front.html.twig should contain the rest of the content that you want to return on the homepage.

An extended example

The template may end up very similar to he page.html.twig. Rather than duplicating 'page.html.twig and then making adjustments in page--front.html.twig, you can extend 'page.html.twig without duplicating any of the content.

To do that, add the extend command at the top of page--front.html.twig.

% extends "page.html.twig" %

This means that page--front.html.twig will inherit everything from page.html.twig.

You can then change parts of it. To change part of the inherited code, it must first be in a Twig block. So in 'page.html.twig, create an empty Twig block for featured content:

{% block featured %}{% endblock %}

And then in page--front.html.twig, override it and include the featured variable:

{% block featured %}
    {{ featured }}
{% endblock %}

The full page--front.html.twig is just a few lines:

{% extends "page.html.twig" %}
{% block featured %}
    {{ featured }}
{% endblock %}

Because 'page.html.twig contains the empty featured Twig block, you can add the featured variable to any other Twig template that extends it if you like (and leave it off templates that should not contain a featured block).

To be the first to get new Drupal 8 tips like this one, jump on my Drupal newsletter.