Tag Filter Menu with active class

Hello,

I’m trying to create a dynamic tag-based menu in the likes of:

<ul>
  <li><a href="projects/">Alles</a></li>
  <li><a href="projects/tag:tag-a">Tag A</a></li>
  <li><a href="projects/tag:tag-b">Tag B</a></li>
  <li><a href="projects/tag:tag-c">Tag C</a></li>
</ul>

I got the basic structure working. Now, when I click on “Tag B”, not only does this filter my content, but also shrink the tag menu to this:

<ul>
  <li><a <a class="active" href="projects/">Alles</a></li>
  <li><a href="projects/tag:tag-b">Tag B</a></li>
</ul>

However, I would like the full menu to be displayed, and (only) the selected tag to be highlighted, like this:

<ul>
  <li><a href="projects/">Alles</a></li>
  <li><a href="projects/tag:tag-a">Tag A</a></li>
  <li><a class="active" href="projects/tag:tag-b">Tag B</a></li>
  <li><a href="projects/tag:tag-c">Tag C</a></li>
</ul>

This is how my project.php controller looks like:

<?php

return function($site, $pages, $page) {

  $articles = page('articles')->grandchildren()->visible();

  if($tag = param('tag')) {
    $articles = $articles->filterBy('tags', $tag, ',');
  }
  $tags = $articles->pluck('tags', ',', false);

  return compact('articles', 'tags', 'tag');
  
};

And the snippet that generates the menu:

<?php $pageTags = $page->tags()->split(); ?>
<?php $p = kirby()->request()->params()->tag(); ?>

<ul class="tags">
  <li><a <?php ecco($tag == $p, 'class="active"') ?> href="/projects">Alles</a></li>
  <?php foreach($tags as $tag): ?>
  <li>
    <a <?= in_array($tag, $pageTags)? 'class="active"':'' ?> href="<?php echo url('projects/tag:' . $tag)?>">
      <?php echo html($tag) ?>
    </a>
  </li>
  <?php endforeach ?>
</ul>

any hints would be much appreciated!

Lucas

You problem is that you pluck the tags from $articles. But if $articles is filtered, you don’t get all the tags. So, you should define your tags based on the original articles collection by either moving your variable definition up in your controller, i.e. place it before (if($tag = param('tag')), or by using the original definition instead of $articles.

Eureka! Of course, now it’s working as expected. Thanks for your help!