Filtering by Multiple Tag -> Retaining first parameter in URL on second tag selection

Hi all,
i am trying to retain the first selected parameter when filtering on a page - with the current solution the hole url changes. I just need the tag to add another parameter to the URL.

    <ul class="tags">
      <?php foreach($farben as $farbe): ?>
      <li>
        <a href="<?= url('home', ['params' => ['farbe' => $farbe]]) ?>">
          <?= html($farbe) ?>
        </a>
      </li>
      <?php endforeach ?>
    </ul>

    <ul class="tags">
      <?php foreach($geschlechter as $geschlecht): ?>
      <li>
    <a href="<?= url(Url::current(), ['params' => ['geschlecht' => $geschlecht]]) ?>">
          <?= html($geschlecht) ?>
        </a>
      </li>
      <?php endforeach ?>
    </ul>

You would have to merge the parameters

['params' => array_merge(params(),['geschlecht' => $geschlecht])])

But. what if someone selects the second choice first? You don’t get to the same URL with what you are doing there…

Do i have to create the URL always as whole, can’t i separate the page->url() from the parameters that are to be added after the URL? - this was it wont matter which is first?

If you use url('home', in both instances, you won’t have this problem either, if the home page is the target page.

You would have to do the merging for both types of links…

Thanks a lot texnixe - just adding the array merge worked!!

>  // fetch all tags
> $farben = page('masken')->children()->listed()->pluck('farbe', ',', true);
> $brands = page('masken')->children()->listed()->pluck('brand', ',', true);
> $prices = page('masken')->children()->listed()->pluck('price', ',', true);
> ?>
> 
> <button class="accordion">Farben</button>
> <div class="panel">
> <ul class="tags autogridtag">
>   <li>
>     <a href="/">
> 	    Alle Masken
>     </a>
>   </li>
>   <?php foreach($farben as $farbe): ?>
>   <li>
>     <a <?php if( param('farbe') === $farbe ) { echo('class="aktiv"'); } ?> href="<?= url($page->url(), ['params' => array_merge(params(),['farbe' => $farbe])]) ?>">
>       <?= html($farbe) ?>
>     </a>
>   </li>
>   <?php endforeach ?>
> </ul>
> </div>
> 
> 
> <button class="accordion">Brands</button>
> <div class="panel">
> 
> <ul class="tags autogridtag">
> 	<li>
>     <a href="/">
> 	    Alle Masken
>     </a>
> 	</li>
> 	<?php foreach($brands as $brand): ?>
> 	<li>
>   	<a <?php if( param('brand') === $brand ) { echo('class="aktiv"'); } ?> href="<?= url($page->url(), ['params' => array_merge(params(),['brand' => $brand])]) ?>">
>       <?= html($brand) ?>
>     </a>
> 	</li>
>   <?php endforeach ?>
> </ul>

it would be really awesome if i could somehow check if there are any brands that are offered in this color, any ideas?=)

Do you mean, so that if a color is selected, only the brands in that color are shown and vice versa, if a brand is selected, only the remaining colors are shown?

Yes, that’s possible. You have to filter the brands by color. How do you get the colors/brands.

Yep - i am plucking them here

<?php

// fetch all tags
$farben = page('masken')->children()->listed()->pluck('farbe', ',', true);
$brands = page('masken')->children()->listed()->pluck('brand', ',', true);
$prices = page('masken')->children()->listed()->pluck('price', ',', true);
?>

Then you have to filter the children if a parameter is set before you pluck

So probably plug them again after a filter ?

You can use when(): https://getkirby.com/docs/reference/objects/pages/when

Then pluck the tags after defining the list of children.

$brand  = param('brand');
$color  = param('farbe');
$price  = param('price');

$products = $page->children()->listed()
    ->when($brand, function ($brand) {
        return $this->filterBy('brand', $brand);
    })
    ->when($color, function ($color) {
        return $this->filterBy('farbe', $color);
    })
    ->when($price, function ($price) {
        return $this->filterBy('price', $price);
    });
$farben = $products->pluck('farbe', ',', true);
// etc.

Yep was using something similar:

<?php
return function ($site, $page) {
  
    /* FILTERS */
  $farbe =param('farbe');
  $brand = param('brand');
  $price = param('price');
  $maskPages = page('masken')->children()->listed()->flip();

  $ausgabeFiltered = $maskPages
    ->when($farbe, function ($farbe) {
      return $this->filterBy('farbe', $farbe, ',');
      $farben = page('masken')->children()->listed()->pluck('farbe', ',', true);

    })
    ->when($brand, function ($brand) {
      return $this->filterBy('brand', $brand,',');
     })
    ->when($price, function ($price) {
      return $this->filterBy('price', $price,',');
    });

 	return $ausgabeFiltered->paginate(100);
};

I just tried your code but it still returns all of the children, not just the filtered ones:

<?php
return function ($site, $page) {
  
$brand  = param('brand');
$color  = param('farbe');
$price  = param('price');

$products = $page->children()->listed()
    ->when($brand, function ($brand) {
        return $this->filterBy('brand', $brand);
    })
    ->when($color, function ($color) {
        return $this->filterBy('farbe', $color);
    })
    ->when($price, function ($price) {
        return $this->filterBy('price', $price);
    });
    
$farben = $products->children()->listed()->pluck('farbe', ',', true);
$brands = $products->children()->listed()->pluck('brand', ',', true);
$prices = $products->children()->listed()->pluck('price', ',', true);
}

You changed the code I provided and those lines don’t make sense, should be $products->pluck('farbe', ',', true) etc., so using the filtered $products, not the children.

Does your controller return the variables to the template?

What is in your template?