I have a portfolio page. The user can filter between different categories, using the links below.
<ul class="filter">
<li><a href="<?= $page->url() ?>">All</a></li>
<li><a href="<?= $page->url() ?>?filter=branding">Branding</a></li>
<li><a href="<?= $page->url() ?>?filter=web">Web</a></li>
<li><a href="<?= $page->url() ?>?filter=graphics">Graphics</a></li>
</ul>
I presume the current active page will stay the ‘Portfolio’ page (this will have the aria-current
). My question is how can I add a class so that I can highlight the current filter/link?
I’ve tried the following, but all four links are highlighted. And I now realise that if the Portfolio page is the current page then what I really want to do is an a class to the active filter.
<ul class="filter">
<li><a <?php e($page->isActive(), 'aria-current') ?> href="<?= $page->url() ?>">All</a></li>
<li><a <?php e($page->isActive(), 'aria-current') ?> href="<?= $page->url() ?>?filter=branding">Branding</a></li>
<li><a <?php e($page->isActive(), 'aria-current') ?> href="<?= $page->url() ?>?filter=web">Web</a></li>
<li><a <?php e($page->isActive(), 'aria-current') ?> href="<?= $page->url() ?>?filter=graphics">Graphics</a></li>
</ul>
I don’t understand what’s going on.
I’d like the ‘All’ filter/page link to be highlighted when someone is on the All page (no filter). Not sure what’s possible?
$page
refers to the current page and in the case of filtering, the page is always the same. So $page->isActive()
will therefore always return true. The only difference is your content on the page.
Such a filter would usually look like this instead of your hard coded example:
<?php
$filterBy = get('filter');
$filters = ['branding', 'web', 'graphics']; // in a real life example, these values would be fetched from the posts
?>
<nav class="filter">
<ul>
<li><a href="<?= $page->url() ?>">All</a></li>
<?php foreach ($filters as $filter): ?>
<li <?= $filter === $filterBy ? 'class="active"' : ''?>><a href="<?= $page->url() ?>?filter=<?= $filter ?>"><?= $filter ?></a></li>
<?php endforeach ?>
</ul>
</nav>
So that means the filter is active when the $filterBy
variable (which fetches the query value from the request) is the same as the value in the loop.
The following is based on the kirbycasts/projects.php at main · getkirby/kirbycasts · GitHub
<?php
$filterBy = get('filter');
$unfiltered = $page->children()->listed();
$projects = $unfiltered
->when($filterBy, function($filterBy) {
return $this->filterBy('categories', $filterBy);
});
$pagination = $projects->pagination();
$filters = $unfiltered->pluck('categories', null, true);
?>
<ul class="filter">
<li><a href="<?= $page->url() ?>">All</a><li>
<?php foreach ($filters as $filter): ?>
<li <?= $filter === $filterBy ? 'class="active"' : ''?>><a href="<?= $page->url() ?>?filter=<?= $filter ?>"><?= $filter ?></a></li>
<?php endforeach ?>
</ul>
<ul class="portfolio">
<?php foreach ($projects as $project): ?>
<li>
<a href="<?= $project->url() ?>">
<?php if ($image = $project->portfolio_thumbnail()->toFile()): ?>
<img src="<?= $image->url() ?>" alt="">
<?php endif ?>
<p><strong><?= $project->heading()->html() ?></strong><br><?= $project->subheading()->html() ?></p>
</a>
</li>
<?php endforeach ?>
</ul>
It’s getting there, but the <ul class="filter">
is weird. It looks like it has combined categories:
Many case-studies should have more than one category.
Also how do I make the words start with an upper case, and to be in the order I want them to be in? I’m also not confident I know how to remove the pagination code (I don’t need the pages to be paginated).
Also how do I add the active class to All when someone is on this page?
Many thanks
If you have a comma separated list of value (like from a tags or multiselect field, then you need to pass the separator:
`$filters = $unfiltered->pluck('categories', ',', true);`