Not active tags disappear

I would like to filter projects by tags.
Here is projects.php controller:

<?php

return function($page) {

  // fetch the basic set of pages
  $projects = $page->children()->listed();

  // add the tag filter
  if($tag = urldecode(param('tag'))) {
    $projects = $projects->filterBy('tags', $tag, ',');
  }

  // fetch all tags
  $tags = $projects->pluck('tags', ',', false);

  return compact('projects', 'tags', 'tag');

};

And here is template:

<?php if(count($projects->pluck('tags', ',', true)) > null): ?>
    <!-- Tags -->
    <div class="column">
      <h3 class="title"><?= $site->labelTags() ?></h3>
      <div class="tags">
        <?php foreach($projects->pluck('tags', ',', true) as $tag): ?>
        <a class="tag is-medium is-light <?php e($tag == urldecode(param('tag')), 'is-dark') ?>" href="<?= url('projects', ['params' => ['tag' => $tag]]) ?>">
          <?= $tag ?>
        </a>
        <?php endforeach ?>
      </div>
    </div>
    <?php endif ?>

It works well, but looks like it shows only the tags of projects, that are in view. For example, when I go to /projects/, then I see all tags, when I filter by some tag, then only those tags are left, that are in filtered projects.

How can I show all tags after applying tag filter?

The problem i think is this bit, because it changes as you move through the pages, since $page means this page (as in, the one you are currently looking at) :slight_smile:

// fetch the basic set of pages
$projects = $page->children()->listed();

I think if you give it a fixed point it will stop that…

// fetch the basic set of pages
$projects = $site->find('YOURPROJECTPARENTPAGE')->children()->listed();

Tried chaning to:
$projects = $site->find('projects')->children()->listed();

and result is the same, By the way, to make this change work, if I understand right, I also had to change top part to: return function($site, $pages, $page) {

You need to do the same on this line too:

  // fetch all tags
  $tags = $projects->pluck('tags', ',', false);

change

  // fetch all tags
  $tags = $site->find('projects')->children()->listed()->pluck('tags', ',', false);

Since that was also picking up on $projects, which was getting filtered higher up.

I use the full set in my own filter, but yes ur right, u need those:

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

Changed, but get the same result.

It’s probably what you are doing in the template then… heres my own tag filter. you dont need to pluck the tags again:

<div class="categories">
  <div class="draw">
    <?php foreach($tags as $tag): ?>
    <div class="block-col">
      <a <?php e(urlencode($tag) == $currenttag, ' class="active"') ?> href="<?= url($section, ['params' => ['tag' => urlencode($tag)]]) ?>">
        <?= html($tag) ?>
      </a>
    </div>
    <?php endforeach ?>
  </div>
</div>

You can get the current tag with this in your controller, and that will put the the active class on the current tab:

  $currenttag = $kirby->request()->params()->tag();

I think I tried something similar before, but then tags are duplicated, probably showing same tag as many times, as there are projects with it.

Well, the above should work, it’s come from my own site. All I can suggest is working through “make a blog” cook book guide, since this is explained in there.

I also did by that example, but it was giving duplicated tags. Maybe the reason is newest Kirby version (3.1.0)

It works fine with the current version. Just pick over what you have done carefully and see where the mistake lies.

Copied one more time the same code, still duplicated.

Interesting, this code https://getkirby.com/docs/cookbook/content/filtering-with-tags#blog-controller makes duplicates but tried with this https://getkirby.com/docs/cookbook/content/filtering-with-tags#tagcloud and it works fine. Thank you for help.

It’s the order in your controller:

<?php

return function($page) {

  // fetch the basic set of pages
  $projects = $page->children()->listed();
  
// to get all tags of all projects, put it here
// fetch all tags
  $tags = $projects->pluck('tags', ',', true); // set to true to only get unique tags
  // add the tag filter
  if($tag = urldecode(param('tag'))) {
    $projects = $projects->filterBy('tags', $tag, ',');
  }



  return compact('projects', 'tags', 'tag');

};

In your template, don’t repeat code, but use the $tags variable throughout:

<?php if(count($tags) > 0): ?>
    <!-- Tags -->
    <div class="column">
      <h3 class="title"><?= $site->labelTags() ?></h3>
      <div class="tags">
        <?php foreach($tags as $tag): ?>
        <a class="tag is-medium is-light <?php e($tag == urldecode(param('tag')), 'is-dark') ?>" href="<?= url('projects', ['params' => ['tag' => $tag]]) ?>">
          <?= $tag ?>
        </a>
        <?php endforeach ?>
      </div>
    </div>
    <?php endif ?>
1 Like