Skip to main content
3 of 8
added 6 characters in body
No Sssweat
  • 31.6k
  • 14
  • 55
  • 91

I can code a little but I'm not very good so I'm having trouble finding an approach to implement this.

I started 7 years ago from zero. I only knew HTML and CSS. I learned and mastered Rules & Views. But like 4 years ago, I ran into scenarios like this one where the existing modules didn't quite do what I needed or felt I had to do overkill/bulky-overhead workarounds. So I learned PHP from free online sources and I learned how to create custom modules in Drupal.

I highly suggest you improve your backend/coding game. Specially since Rules in D8 is barebones compared to D7.

I tried to build this in Views. The problem I encountered was that it is very difficult to iterate through the subdivision entity reference field and filter out the previous and next links.

While it's possible to programmatically solve it with Views, it feels over-kill/unnecessary to do this in Views just for prev and next links. A better approach is to create prev_url and next_url variables for Twig. Using a preprocess function we can create and pass those variables to the appropriate template file, node.html.twig in this case.

I put lots of comments, so hopefully you'll learn a thing or two.

In mytheme.theme

/**
 * Implements hook_preprocess_HOOK() for node.html.twig.
 */
function mytheme_preprocess_node(&$variables) {
  $node = $variables['elements']['#node']; // obtain current page node object
  if ($node->getType() == 'page') { // check it's a "page" content type
    $page_nid = $node->id(); // get the current page node id
    // get Chapter nids using Entity Field Query
    $query = \Drupal::entityQuery('node')
      ->condition('type', 'chapter')
      ->condition('field_reference', $page_nid); // check if current page NID is set on any Chapter's reference field
    $chapter_nids = $query->execute(); // returns array of Chapter nids
    if (!empty($chapter_nids)) { // check we have a result
      $chapter_nid = reset($chapter_nids); // Extracts the first array value, since we assume current page can only belong to one Chapter.
      $chapter_node = Drupal\node\Entity\Node::load($chapter_nid); // load chapter node
      $referenced_page_nodes = $chapter_node->field_reference; // get referenced nodes
      foreach ($referenced_page_nodes as $key => $referenced_item) { // loop though referenced nodes
        if ($referenced_item->entity) {
          if ($node->id() == $referenced_item->entity->id()) { // check if current page nid equals referenced nid
            $prev_key = $key - 1; // we'll use these keys to access prev/next array values
            $next_key = $key + 1;
            if (!empty($referenced_page_nodes[$prev_key])) { // check if previous key exists
              $prev_url = $referenced_page_nodes[$prev_key]->entity->toUrl()->toString(); // get prev URL
              $variables['prev_url'] = $prev_url; // creates prev_url variable in node.html.twig
            }
            if (!empty($referenced_page_nodes[$next_key])) { // check if next key exists
              $next_url = $referenced_page_nodes[$next_key]->entity->toUrl()->toString(); // get next URL
              $variables['next_url'] = $next_url; // creates next_url variable in node.html.twig
            }
            break; // since we found it, exit from loop as no point in continuing to loop through.
          }
        }
      }
    }
  }
}

Note: Rename field_reference (2 places) to the machine name of your actual reference field in Chapter content type.

In node.html.twig, you can place them after the {{ content }} part

{% if prev_url is not empty %}
  <span><a href="{{ prev_url }}">{{ 'Previous page'|t }}</a></span>
{% endif %}
{% if next_url is not empty %}
  <span><a href="{{ next_url }}">{{ 'Next page'|t }}</a></span>
{% endif %}
No Sssweat
  • 31.6k
  • 14
  • 55
  • 91