1

In my theme's .theme file I have the book navigation block stored in a twig variable like so.

function mytheme_preprocess_page(&$variables){
    $book = \Drupal\block\Entity\Block::load('booknavigation');
    $variables['book'] = \Drupal::entityTypeManager()
        ->getViewBuilder('block')
        ->view($book);
}

I'm then calling it in my page.html.twig template like so

<div class="sidebar">
    {{ book }}
</div>
<div class="content">
    {{ page.content }}
</div>

However on basic pages that are book pages, sibling book items are shown but the top level book page is not. Even when visiting the top level book page the link is not shown in the book block.

Why isn't the top level of the book ever displayed? And is there a way I can get the top level to be shown?

UPDATE: I've looked at creating a book-tree.html.twig. The contents are below

{% import _self as book_tree %}

{#
  We call a macro which calls itself to render the full tree.
  @see http://twig.sensiolabs.org/doc/tags/macro.html
#}
{{ book_tree.book_links(items, attributes, 0) }}

{% macro book_links(items, attributes, menu_level) %}
  {% import _self as book_tree %}
  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass('menu') }}>
    {% else %}
      <ul class="menu">
        {{ dump(book_tree|keys) }}
    {% endif %}
    {% for item in items %}
      {%
        set classes = [
          'menu-item',
          item.is_expanded ? 'menu-item--expanded',
          item.is_collapsed ? 'menu-item--collapsed',
          item.in_active_trail ? 'menu-item--active-trail',
        ]
      %}

      <li{{ item.attributes.addClass(classes) }}>
        {{ link(item.title, item.url) }}
        {% if item.below %}
          {{ book_tree.book_links(item.below, attributes, menu_level + 1) }}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}

But I don't see where I can access the top level.

UPDATE: I found a workaround but I'm looking for a solution that does not require that workaround. Users should not have to create an empty page with the same title just to act as the non displayed top level.

4
+100

This looks like a bug in the book module.

I have added a patch for it.

https://www.drupal.org/node/2827910#comment-11780887

You could add that patch, or create a new block that overrides the BookNavigationBlock,

in a custom module add /src/Plugin/Block/CustomBookNavigationBlock.php:

  namespace Drupal\mymodule\Plugin\Block;

  use Drupal\book\Plugin\Block\BookNavigationBlock;

    /**
     * Provides a 'Book navigation' block.
     *
     * @Block(
     *   id = "custom_book_navigation",
     *   admin_label = @Translation("Book navigation - Customized"),
     *   category = @Translation("Menus")
     * )
     */
    class CustomBookNavigationBlock extends BookNavigationBlock {

      /**
       * {@inheritdoc}
       */
      public function build() {
        $current_bid = 0;

        if ($node = $this->requestStack->getCurrentRequest()->get('node')) {
          $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid'];
        }
        if ($this->configuration['block_mode'] == 'all pages') {
          return parent::build();
        }
        elseif ($current_bid) {
          // Only display this block when the user is browsing a book and do
          // not show unpublished books.
          $nid = \Drupal::entityQuery('node')
            ->condition('nid', $node->book['bid'], '=')
            ->condition('status', NODE_PUBLISHED)
            ->execute();

          // Only show the block if the user has view access for the top-level node.
          if ($nid) {
            $tree = $this->bookManager->bookTreeAllData($node->book['bid'], $node->book);
            return $this->bookManager->bookTreeOutput($tree);
          }
        }
        return array();
      }

    }
  • Thanks for that! Is there a way to load all items (links) of the book as expanded when on the parent page? I also want to comment that it worked for me, but i had to adjust the spacing and indentation when copying the code from here to make it show in the list of blocks, incase someone else runs into the wondering why it doesnt work ;) – petergus Mar 18 '17 at 17:12
  • I have posted my above comment as a question (as well as a git repo of the module) at drupal.stackexchange.com/q/231733/10759 @oknate – petergus Mar 19 '17 at 18:50
  • 1
    removing , $node->book works to show the whole book navigation tree actually. drupal.stackexchange.com/a/231998/10759 – petergus Mar 22 '17 at 10:44
  • I am now trying to show the whole book tree on every node (also non-book nodes), do you know how this is possible? – petergus Mar 23 '17 at 16:18
0

I ended up solving my issue by creating an empty book page that isn't meant to be visited to act as the top level. And just added everything as a child of the book. Though I'm surprised that the possibility of letting users click on a link to the topmost level of a book wasn't considered by the module.

However I would prefer not to use this route. I'd like the user to be able to create books using the book outline tab on basic pages so they don't have to create empty book pages.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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