Filtering all works even though the page was paginated

Hello,
I found one problem when I surf the page which is it’s not possible to filter the paginated page.
Like this…

As you can see, in page : 5, the web page cannot filter works.
So I wonder if it is possible to filter all works at the paginated web page ? (the pagination might be reset and filter all works at the page :1)

This is my code

<?php

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

  $workcategory = param('category');
  $worktimeline = param('timeline');

  $artworks = page('home/works')->children()->listed();
  $categories = $artworks->pluck('category', ',', true);
  $timelines = $artworks->pluck('timeline', ',', true);
  
  $artworks =  $artworks
      ->when($workcategory, function ($workcategory) {
          return $this->filterBy('category', $workcategory, ',');
      })
      ->when($worktimeline, function ($worktimeline) {
          return $this->filterBy('timeline', $worktimeline);
      });
    

      $query   = get('q');
      $results = $artworks->search($query, 'title');
    
  // pagination
  $artworks   = $artworks->paginate(30);
  $pagination = $artworks->pagination();



  return compact('artworks', 'categories','timelines', 'query', 'results', 'pagination');

};

Please help!
Thank you:)

Could you please post your template code as well?

Sure!
This is the one

<?php if ($works = page('home/works')): ?>
<div id="container__contents" class="container--works">
    <div class="container--works__filters">
        <?php snippet('filters/category') ?>
        <?php snippet('filters/timeline') ?>
    </div>
    <div class="container--works">
        <?php snippet('loader') ?>
        <?php foreach ($artworks as $p): ?>
            <div class="container--works--items">
                <div class="container--works--items__thumbnail">
                    <?php if ($mainImg = $p->workImgMain()->toFile()): ?>
                        <img class="worksmainImg" src="<?= $mainImg->url() ?>">
                    <?php endif ?>
                    <span>
                        <?= $p->title()->kt() ?>
                    </span>
                </div>
         <?php endforeach ?>
        <div class="bottom">
            <?php snippet('pagination') ?>
            <?php snippet('copyright') ?>
        </div>
    </div>
</div>
<?php endif ?>

Those snippets contain the interesting part…

Oh I see,
This the code of ‘filters/category’

<div class="filter">
  <p class="filter--title">Category</p>
  <ul class="filter--category">
  <?php $activeTag = param('category'); ?>
  <?php $cate = kirby()->request()->params()->tag(); ?>
    <li>
      <a <?php e($categories == $cate, 'class="activebtn"') ?>  href="<?= url($page->url()) ?>">All</a>
    </li>
    <?php foreach($categories as $categories): ?>
    <li>
      <a <?= $activeTag === $categories ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => array_merge(params(),['category' => $categories])]) ?>">
        <?= html($categories) ?>
      </a>
    </li>
    <?php endforeach ?>
  </ul>
</div>


Hm, this doesn’t make sense, $categories is defined as an array of all your categories plucked from $artworks. Comparing that to the parameter string, will not do what you expect.

Don’t have time now to look into this in details…

Ok, I think your snippet should look like this:

div class="filter">
  <p class="filter--title">Category</p>
  <ul class="filter--category">
  <?php $activeTag = param('category'); ?>

    <li>
      <a <?php 
  // All is active if no parameter is set!
  e(empty($activeTag), 'class="activebtn"') ?>  href="<?= url($page->url()) ?>">All</a>
    </li>
    <?php 
   // never use the same variable for the array and the item!
   foreach($categories as $category): ?>
    <li>
      <a <?= $activeTag === $category ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => array_merge(params(),['category' => $category])]) ?>">
        <?= html($category) ?>
      </a>
    </li>
    <?php endforeach ?>
  </ul>
</div>

Thank you for your reply!
I change the templates like this but still web doesn’t work on the page “http://…/works/page:5/timeline:2014”
It only works when the filtered page has page:5.

<div class="filter">
  <p class="filter--title">Category</p>
  <ul class="filter--category">
  <?php $activeTag = param('category'); ?>
  <?php $cate = kirby()->request()->params()->tag(); ?>
    <li>
      <a <?php  e(empty($activeTag), 'class="activebtn"') ?>  href="<?= url($page->url()) ?>">All</a>
    </li>
    <?php foreach($categories as $category): ?>
    <li>
      <a <?= $activeTag === $category ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => array_merge(params(),['category' => $category])]) ?>">
        <?= html($category) ?>
      </a>
    </li>
    <?php endforeach ?>
  </ul>
</div>

<div class="filter">
  <p class="filter--title">Timeline</p>
  <ul class="filter--category">
  <?php $activeTag = param('timeline'); ?>
    <?php foreach($timelines as $timeline): ?>
    <li>
      <a <?= $activeTag === $timeline ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => array_merge(params(),['timeline' => $timeline])]) ?>">
        <?= html($timeline) ?>
      </a>
    </li>
    <?php endforeach ?>
  </ul>
</div>

Please comment this if you have any idea…!
Thank you

This is the problem. You merge the parameters here, but the page number parameter doesn’t make sense for a new category, because the number of pages can change. Therefore, pagination should never be included here.

Oh, Thank you for answering!
Like you said, I changed the code like this but now from this code, I just got a new problem.
If I change the code like this, I cannot select two filter at once like this : (/category:Objects/time:2020).
Only one filter works at once currently. :scream_cat:

<li>
  <a <?= $activeTag === $category ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => ['category' => $category]]) ?>">
    <?= html($category) ?>
  </a>
</li>
...
 <li>
    <a <?= $activeTag === $timeline ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => ['timeline' => $timeline]]) ?>">
      <?= html($timeline) ?>
    </a>
  </li>

Do you have any solution at this situation?

<?php 
$params = [];
if (param('timeline') {
  $params['timeline'] = param('timeline'];
}

if (param('category') {
  $params['category'] = param('category'];
}
?>

      <a <?= $activeTag === $category ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => array_merge($params['timeline'] ?? [],['category' => $category])]) ?>">

And then the same for the other link, using $params['category'] instead.

Hi, I have one more question! Sorry that I keep asking…
Like you told me, I changed the code like this

<?php 
      $params = [];
      if (param('timeline')) {
        $params['timeline'] = param('timeline');
      }

      if (param('category')) {
        $params['category'] = param('category');
      }
      ?>
      <a <?= $activeTag === $category ? ' class="activebtn"' : '' ?> href="<?= url($page->url(), ['params' => array_merge($params['timeline'] ?? [],['category' => $category])]) ?>">
        <?= html($category) ?>
      </a>

But I keep getting this error so that I cannot access to the filter at all
: array_merge(): Expected parameter 1 to be an array, string given

Do you think I should put some code on the controller.php?

<?php

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

  $workcategory = param('category');
  $worktimeline = param('timeline');

  $artworks = page('home/works')->children()->listed();
  $categories = $artworks->pluck('category', ',', true);
  $timelines = $artworks->pluck('timeline', ',', true);
  
  $artworks =  $artworks
      ->when($workcategory, function ($workcategory) {
          return $this->filterBy('category', $workcategory, ',');
      })
      ->when($worktimeline, function ($worktimeline) {
          return $this->filterBy('timeline', $worktimeline);
      });
    

      $query   = get('q');
      $results = $artworks->search($query, 'title');
    
  // pagination
  $artworks   = $artworks->paginate(30);
  $pagination = $artworks->pagination();



  return compact('artworks', 'categories','timelines', 'query', 'results', 'pagination');

};

Thank you!

Oops, that was silly of me, sorry should have been

array_merge($params , ['category' => $category])])
1 Like

Now it works!
Thank you so much :slight_smile: