Skip to main content

Drupal 8: Embed a node adhoc into a view

Updated by Tim Rabbetts on
technology, laptop, keyboard

I had the need recently to embed nodes at given point in a view in Drupal 8.  Could be used for adverts but in this case I had a settings form which had entity reference auto complete field which referenced some content I want to promot on homepage within the view.  First thing is to build a preprocess view function.

function MYMODULE_theme_preprocess_views_view_unformatted(array &$variables) {

  // Homepage view, first page insert promoted nodes.
  if ($variables['view']->id() == 'homepage' &&
      $variables['view']->current_display == 'page_1' &&
      $variables['view']->getCurrentPage() == 0) {

    $promoted = \Drupal::state()->get('homepage_hero_settings.homepage_promoted_content_items');
    $structure = [
      ['index' => 1, 'view_mode' => 'teaser_half_overflow'],
      ['index' => 3, 'view_mode' => 'teaser_wide'],
      ['index' => 6, 'view_mode' => 'teaser_half_overflow'],
      ['index' => 9, 'view_mode' => 'teaser_wide'],
      ['index' => 10, 'view_mode' => 'teaser_half'],
      ['index' => 11, 'view_mode' => 'teaser_half'],
    ];

    foreach ($promoted as $key => $promote) {
      \Drupal::service('myservice')
        ->insertNodeIntoView($variables, $structure[$key]['index'], $promote['target_id'], $structure[$key]['view_mode']);
    }
  }

}

I also built a service to house the process of inserting the node into the view, see below:


  /**
   * Insert a node into a view at a given point.
   *
   * @param array $variables
   *   Supplied via preprocess hook.
   * @param int $insert_row
   *   Where to insert the node in the view.
   * @param int $nid
   *   The node id of the content to insert.
   * @param string $view_mode
   *   How to disaply the node.
   */
  public function insertNodeIntoView(array &$variables, $insert_row, $nid, $view_mode) {
    $node = Node::load($nid);
    $view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
    $insert = [
      'content' => $view_builder->view($node, $view_mode),
    ];
    array_splice($variables['rows'], $insert_row, 0, [$insert]);
  }

Thats it, took ages to figure out but this works nicely.  I limited it to page 1 but if you wanted you could continue this through pagination.

Add new comment