# Filtering Content on a page

**URL:** <https://forum.getkirby.com/t/filtering-content-on-a-page/6760>\
**Category:** Questions\
**Tags:** v2\
**Created:** [February 26, 2017, 10:49am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760 "2017-02-26T10:49:34Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 10:49am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/1 "2017-02-26T10:49:34Z")

</div>

Hello,

iam searching for a way to filter content on a page, so for example iam working  
on a job portal and have a list of fifty jobs, but just wanna display all jobs  
in a specific city by selecting from a dropdown menu.

Is there a way that works with pagination? For me it does´t matter  
if its a javascript solution or php, also i thought about to use  
the search as filter. Do this makes sense?

Thank you for any help.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 11:08am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/2 "2017-02-26T11:08:39Z")

</div>

See this cookbook recipe: [https://getkirby.com/docs/cookbook/filtering#using-filters-with-forms-e-g-select-fields](https://getkirby.com/docs/cookbook/filtering#using-filters-with-forms-e-g-select-fields). Of course, you can paginate the resulting results like any other page collections.

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 11:16am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/3 "2017-02-26T11:16:28Z")

</div>

i see that i need a controller script for it, can i have two controller files for one template?  
Do i have to set something up in my blueprint to test the script?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 11:21am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/4 "2017-02-26T11:21:05Z")

</div>

No, you can’t have two controllers. But why would you need them?

> [@SandroIeva](#):
>
> Do i have to set something up in my blueprint to test the script?

The script as is requires certain fields (color, brand, size) to be present in your pages. But of course, you can just adapt it to filter by the fields present in your content files.

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 11:25am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/5 "2017-02-26T11:25:26Z")

</div>

Ok…no i don´t need them. I thought i had a form on the page, but its on the landing page,  
where people can demand on a job.

Your script looks like what i need, but its hard for me to understand.  
What i have to do to set it up?

Is… $item = $page-\>children()-\>color() for example?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 11:31am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/6 "2017-02-26T11:31:41Z")

</div>

All you need is the form with the select fields in your template where you display your jobs, and the controller code in the controller for that template. Of course, you have to adapt the fields used in the controller/form to fit your filter criteria.

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 11:40am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/7 "2017-02-26T11:40:03Z")

</div>

Can you explain me where items come from?

```auto
<?php foreach($color as $item): ?>

```

Do have to define item?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 11:44am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/8 "2017-02-26T11:44:03Z")

</div>

All variable like `$color,`$brand`and`$sizes` are defined in the controller. You don’t have to define $item as it get’s defined in the foreach loop. Please read about using foreach loop in PHP if you don’t know how they work. You need a basic understanding of PHP to be able to do this, we can’t offer that sort of support here.

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 11:47am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/9 "2017-02-26T11:47:44Z")

</div>

Yes i understand loops, but don´t understand the script…so what i have changed:

```auto
<form id="filters" method="post">
  <!-- give the select the name of the category to filter by -->
  <select name="ort" onchange="this.form.submit()">
    <option selected value="">Select a color</option>

    <!-- let's fill the options with our colors -->
    <?php foreach($ort as $item): ?>
      <!-- we don't want empty items -->
      <?php if(!$item) continue ?>

      <!-- set the option to selected if selected -->
      <option<?php e(isset($data['ort']) && $data['ort'] == $item, ' selected') ?> value="<?php echo $item ?>"><?php echo $item?></option>
    <?php endforeach ?>
  </select>
</form>

```

i replaced color with ort because i have a field ort in my blueprint. And this is my controller:

```auto
<?php

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

  $ort = $page->children()->pluck('ort', null, true);
  $keys = array('ort');

  // return all children if nothing is selected
  $projects = $page->children()->visible();

  // if there is a post request, filter the projects collection
  if(r::is('POST') && $data = get()) {
    $projects = $page->children()->visible()->filter(function($child) use($keys, $data) {

      // loop through the post request
      foreach($data as $key => $value) {

        // only act if the value is not empty and the key is valid
        if($value && in_array($key, $keys)) {

          // return false if the child page's category and value don't match
          if(!$match = $child->$key() == $value) {
            return false;
          }
        }
      }

      // otherwise return the child page
      return $child;

    });
  }
  return compact('products', 'ort', 'data');
};

```

but the selector is empty

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 11:53am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/10 "2017-02-26T11:53:53Z")

</div>

Ok…seems like the fields have to be filled all with info to work. now i see the value in my selector, but the filter does´t work 😕

here is my content i wanna filter:

```auto

			<div class="row small_pad">
				<?php foreach($nom_list as $proj):?>
				<div class=" col-sm-12 col-md-6 col-lg-6 wow fadeIn" data-wow-delay="0.5s" data-wow-duration="1.5s">
				<div class="teaser_box">
				<h2><span class="white_t"><?php echo $proj->title() ?></span></h2>	
				<p>Einsatzort: <span class="subtitle"><?php echo $proj->ort() ?></span></p>
				<p><?php echo excerpt($proj->beschreibung(), 100) ?></p>
				<p><a class="link_b" href="<?php echo $proj->url() ?>">JETZT ANSEHEN<span class="arrow_icon"></span></a></p>
				</div>
				</div>
			<?php endforeach ?>	
			</div>	

```

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 11:56am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/11 "2017-02-26T11:56:00Z")

</div>

You can use the following syntax to fetch the values from all pages instead even if some are empty:

```auto
$ort = $page->children()->pluck('ort', ',', true);

```

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 11:57am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/12 "2017-02-26T11:57:41Z")

</div>

Where is `$nom_list` defined? This is what you have to filter in your controller!

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 11:58am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/13 "2017-02-26T11:58:50Z")

</div>

its defined in my template on the top:

```auto
$nom_list = $page->children()->flip()->visible()->paginate(6);

```

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 11:59am UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/14 "2017-02-26T11:59:33Z")

</div>

And where do you filter the list? Because all I see in the controller is projects, not `$nom_list`.

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 12:06pm UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/15 "2017-02-26T12:06:28Z")

</div>

Mmmh…Ok: So i replace it in my controller:

```auto
  // return all children if nothing is selected
  $nom_list = $page->children()->visible();

  // if there is a post request, filter the projects collection
  if(r::is('POST') && $data = get()) {
    $nom_list = $page->children()->visible()->filter(function($child) use($keys, $data) {

```

anything else i have to change, does´t work for me?

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 12:11pm UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/16 "2017-02-26T12:11:02Z")

</div>

This my controller:

```auto
<?php

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

  $ort = $page->children()->pluck('ort', ',', true);
  $keys = array('ort');

  // return all children if nothing is selected
  $nom_list = $page->children()->visible();

  // if there is a post request, filter the projects collection
  if(r::is('POST') && $data = get()) {
    $nom_list = $page->children()->visible()->filter(function($child) use($keys, $data) {

      // loop through the post request
      foreach($data as $key => $value) {

        // only act if the value is not empty and the key is valid
        if($value && in_array($key, $keys)) {

          // return false if the child page's category and value don't match
          if(!$match = $child->$key() == $value) {
            return false;
          }
        }
      }

      // otherwise return the child page
      return $child;

    });
  }
  return compact('products', 'ort', 'data');
};

```

and this is my template:

```auto

<?php
$nom_list = $page->children()->flip()->visible()->paginate(6);
$pagination = $nom_list->pagination();
?>

<?php snippet('header') ?>
<div class="grey_bg">
	<div class="container small_pad min_h">
		<div class="row"><div class="trenner"></div></div>	
		

<form id="filters" method="post">
  <!-- give the select the name of the category to filter by -->
  <select name="ort" onchange="this.form.submit()">
    <option selected value="">Select a color</option>

    <!-- let's fill the options with our colors -->
    <?php foreach($ort as $item): ?>
      <!-- we don't want empty items -->
      <?php if(!$item) continue ?>

      <!-- set the option to selected if selected -->
      <option<?php e(isset($data['ort']) && $data['ort'] == $item, ' selected') ?> value="<?php echo $item ?>"><?php echo $item?></option>
    <?php endforeach ?>
  </select>
</form>
				
			
			<div class="row small_pad">
				<?php foreach($nom_list as $proj):?>
				<div class=" col-sm-12 col-md-6 col-lg-6 wow fadeIn" data-wow-delay="0.5s" data-wow-duration="1.5s">
				<div class="teaser_box">
				<h2><span class="white_t"><?php echo $proj->title() ?></span></h2>	
				<p>Einsatzort: <span class="subtitle"><?php echo $proj->ort() ?></span></p>
				<p><?php echo excerpt($proj->beschreibung(), 100) ?></p>
				<p><a class="link_b" href="<?php echo $proj->url() ?>">JETZT ANSEHEN<span class="arrow_icon"></span></a></p>
				</div>
				</div>
			<?php endforeach ?>	
			</div>	

```

i don´t understand why this does´t work 😕

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 1:04pm UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/17 "2017-02-26T13:04:40Z")

</div>

This does not work for two reasons:

- you do not return `$nom_list` from your controller
- instead you define `$nom_list` in the template again.

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 1:29pm UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/18 "2017-02-26T13:29:32Z")

</div>

Thank you so far, but iam really confused with this script so i updated my template and deleted the nom\_list definition and add the controller to this:

```auto
<?php

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

  $ort = $page->children()->pluck('ort', ',', true);
  $keys = array('ort');

  // return all children if nothing is selected
  $nom_list = $page->children()->flip()->visible()->paginate(6);

  // if there is a post request, filter the projects collection
  if(r::is('POST') && $data = get()) {
    $nom_list = $page->children()->visible()->filter(function($child) use($keys, $data) {

      // loop through the post request
      foreach($data as $key => $value) {

        // only act if the value is not empty and the key is valid
        if($value && in_array($key, $keys)) {

          // return false if the child page's category and value don't match
          if(!$match = $child->$key() == $value) {
            return false;
          }
        }
      }

      // otherwise return the child page
      return $child;

    });
  }
  return compact('nom_list', 'ort', 'data');
};

```

But nothing happens, also $child confuse me, where this come from? It always showing all entries, so it seems that the filtering does´t work

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [February 26, 2017, 3:02pm UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/19 "2017-02-26T15:02:54Z")

</div>

`$child` is just a variable that is used to refer to a single element of the collection inside the filter callback function.

What does your template look like now?

---

<div class="post-metadata">

**Author:** ![SandroIeva](https://avatars.discourse-cdn.com/v4/letter/s/87869e/32.png) [@SandroIeva](https://forum.getkirby.com/u/SandroIeva)\
**Post date:** [February 26, 2017, 3:09pm UTC](https://forum.getkirby.com/t/filtering-content-on-a-page/6760/20 "2017-02-26T15:09:20Z")

</div>

This is my whole template, maybe the pagination on top can be delete:

```auto

<?php

$pagination = $nom_list->pagination();
?>

<?php snippet('header') ?>
<div class="grey_bg">
	<div class="container small_pad min_h">
		<div class="row"><div class="trenner"></div></div>	
		

<form id="filters" method="post">
  <select name="ort" onchange="this.form.submit()">
    <option selected value="">Select a city</option>

    <?php foreach($ort as $item): ?>
      <?php if(!$item) continue ?>
      <!-- set the option to selected if selected -->
      <option<?php e(isset($data['ort']) && $data['ort'] == $item, ' selected') ?> value="<?php echo $item ?>"><?php echo $item?></option>
    <?php endforeach ?>
  </select>
</form>							
			<div class="row small_pad">
				<?php foreach($nom_list as $proj):?>
				<div class=" col-sm-12 col-md-6 col-lg-6 wow fadeIn" data-wow-delay="0.5s" data-wow-duration="1.5s">
				<div class="teaser_box">
				<h2><span class="white_t"><?php echo $proj->title() ?></span></h2>	
				<p>Einsatzort: <span class="subtitle"><?php echo $proj->ort() ?></span></p>
				<p><?php echo excerpt($proj->beschreibung(), 100) ?></p>
				<p><a class="link_b" href="<?php echo $proj->url() ?>">JETZT ANSEHEN<span class="arrow_icon"></span></a></p>
				</div>
				</div>
			<?php endforeach ?>	
			</div>	
		
			<div class="row text-left small_pad">
			<div class="col-xs-12 col-lg-12">	
<?php if($nom_list->pagination()->hasPages()): ?>
<nav class="pagination">

  <?php if($nom_list->pagination()->hasNextPage()): ?>
  <a class="next" href="<?php echo $nom_list->pagination()->nextPageURL() ?>">&lsaquo; weitere Jobs</a>
  <?php endif ?>
	

  <?php if($nom_list->pagination()->hasPrevPage()): ?>
  <a class="prev" href="<?php echo $nom_list->pagination()->prevPageURL() ?>">vorherige Jobs &rsaquo;</a>
  <?php endif ?>

</nav>
<?php endif ?>
				
			</div>	
			</div>
			
			
	</div>
</div>
<?php snippet('footer') ?>

```

[Next page](https://forum.getkirby.com/t/filtering-content-on-a-page/6760.md?page=2)
