On the 1st level pages from our main menu I would like to list all the 2nd level child page titles from that page and corresponding images from those children pages' content fields. I would like them ordered the same as they are in the menu. I am using the path-auto pattern of [parent-url]/[page-title]. I'm open to any suggestions on how to do this.

I've looked into trying to create this with a view block or even a view REST feed but it appears I cannot get attributes from a menu in views in Drupal 8 to use to sort or filter the items. I tried to do this with a menu block but it appears I cannot add fields such as an image to show.

1 Answer 1


I finally had time to come back to this, so I'll answer my own question as I believe the following solves it. This code could for sure use some refactoring & cleaning up. I'm very new to Drupal 8 & I'm fairly new to Drupal in general. Feel free to suggest improvements.

 * @file
 * Displays children pages as a block

namespace Drupal\child_pages_display\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Url;
use Drupal\Core\Path;
use Drupal\Core\Menu;
 * Provides a 'Next Previous' block.
 * @Block(
 *   id = "child_page_block",
 *   admin_label = @Translation("Child Page Block"),
 *   category = @Translation("Blocks")
 * )
class ChildPageBlock extends BlockBase {
  public function build(){
    $menu_tree = \Drupal::menuTree();
    $menu_name = 'main';

    // Build the typical default set of menu tree parameters.
    $parameters = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);
    $expandedParents = $parameters->expandedParents;
    $root = current($expandedParents);
    $parameters = new \Drupal\Core\Menu\MenuTreeParameters();

    // Load the tree based on this set of parameters.
    $tree = $menu_tree->load($menu_name, $parameters);

    //Set Cache for block
    $cache['max-age'] = 3600;
    $cache['contexts'][] = 'url.path';
    $cache['tags'][] = $root;

    //Get node IDs from menu
    $nids = array();
    foreach($tree as $item){
      $nids[] = $item->link->getUrlObject()->getRouteParameters()['node'];

    //Load nodes & generate content from nodes
    $nodes = (!empty($nids)) ? entity_load_multiple('node', $nids) : array();
    if (!empty($nodes) && is_array($nodes)){
      foreach($nodes as $key=>$val) {
        $nodeContent = array(
          '#prefix' => '<div class="block-child-page-menu">',
          '#suffix' => '</div>'
        $url = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$key);

        //Get image thumbnail from content & use specified image style
        if(null !== $val->get('field_thumbnail')->entity){
          $imgPath = ($val->get('field_thumbnail')->entity->uri->value);
          $imgCroppedPath = \Drupal\image\Entity\ImageStyle::load('basic_page_thumbnail')->buildUrl($imgPath);
          $img = ($imgPath != '') ? '<img src="' . $imgCroppedPath . '" />' : '';
          $img = "";
        $nodeContent['#markup'] = '<a href="'.$url.'">' .
            '<h2>' . $val->getTitle() . '</h2>' .
            $img .
        $content[] = $nodeContent;
      //Menu has no nodes
      $content['#markup'] = '';
    //Add cache & css library to block
    $content['#cache'] = $cache;
    $content["#attached"] = array('library' => array('child_pages_display/child_pages_display_css'));
    return $content;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.