Jump to content

Filter with multiple checkboxes


combicart
 Share

Recommended Posts

I'm currently working on a page which shows an overview of Events. I would like to add a filter so that users can view the Events that are in their neighbourhood or that belong to a specific category.

I'm using the following code for the form:

<form action="." method="get" id="events_filter">
  <?php foreach ($pages->get(1104)->children() as $category) : ?>
    <div class="flex items-center">
        <input id="<?= $category->id; ?>" name="category" value="<?= $category->id; ?>" type="checkbox" class="text-gold-600 h-4 w-4 rounded border-brown-300 focus:ring-gold-500"/>
        <label for="<?= $category->id; ?>" class="ml-3 text-brown-800"><?= $category->title; ?></label>
    </div>
  <?php endforeach; ?>
  
  <?php foreach ($pages->find("template=location") as $location) : ?>
    <div class="flex items-center">
        <input id="<?= $location->id; ?>" name="location" value="<?= $sanitizer->kebabCase($location->title); ?>" type="checkbox" class="text-gold-600 h-4 w-4 rounded border-brown-300 focus:ring-gold-500" />
        <label for="<?= $location->id; ?>" class="ml-3 text-brown-800"><?= $location->title; ?></label>
    </div>
  <?php endforeach; ?>
  <button type="submit" id="events_filter" class="text-md flex w-full justify-center rounded bg-orange-500 px-8 py-3 font-semibold text-white transition hover:bg-orange-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-orange-200">Filter</button>
</form>

On the page itself I've added the following code to get the categories and locations:

//Default selector to get ALL events
$selector = "template=event";

// Get cateogry and location variables and sanitize
$category = $sanitizer->selectorValue($input->get->category);
$location = $sanitizer->selectorValue($input->get->location);

if ($category) {
    $selector = $selector .= ",event_categories=$category";
}
if ($location) {
    // See how this uses greater than or equal to
    $selector = $selector .= ",event_locations.title=$location";
}

$events = $pages->find($selector);

There is only one thing that I can't get to work. When a user currently selects multiple checkboxes, only the last checkbox will be used inside the filter. Ideally when a user selects multiple checkboxes they all will be used inside the filter.

Is there someone that could point me into the right direction on how to achieve that?

Link to comment
Share on other sites

When dealing with checkbox or radiobox inputs, if the name of the individual checkbox/radio inputs remains the same, you can set the name to an array-style, such as:

  <?php foreach ($pages->get(1104)->children() as $category) : ?>
    <div class="flex items-center">
        <input id="<?= $category->id; ?>" name="category[]" value="<?= $category->id; ?>" type="checkbox" class="text-gold-600 h-4 w-4 rounded border-brown-300 focus:ring-gold-500"/>
        <label for="<?= $category->id; ?>" class="ml-3 text-brown-800"><?= $category->title; ?></label>
    </div>
  <?php endforeach; ?>

Note the name="category[]". This then assigns the returned value(s) of the form input into the $_GET['category'] variable as an array. The way it's written now, whatever is chosen last will overwrite what was set/chosen prior, which is why you're experiencing what you're experiencing.

Unlike a (multi)select element that provides option values that are assigned to the select's name, the radio and checkbox items are individual inputs with an expected (by us) association.

  • Like 4
Link to comment
Share on other sites

@BrendonKoz Thanks! I've added the change and now it works like expected.

One other question. I would like to make the checkbox 'checked' when one or more filters are enabled. I tried doing this with the checked() method and with in_array but so far I'm not able to get the results that I want.

Is there a way to add the `checked` option to a checkbox when it's active in the filter?

Link to comment
Share on other sites

If I understand correctly that the clicked checkboxes are already marked as checked after submitting the form, you could solve it as follows:

$selectedCategories = (isset($input->get->category)) ? $input->get->category : [];

<?php foreach ($pages->get(1104)->children() as $category) : ?>
    <div class="flex items-center">
        <input id="<?= $category->id; ?>" name="category[]" value="<?= $category->id; ?>" type="checkbox" class="text-gold-600 h-4 w-4 rounded border-brown-300 focus:ring-gold-500"<?php echo in_array($category->id, $selectedCategories) ? ' checked' : '' ?>/>
        <label for="<?= $category->id; ?>" class="ml-3 text-brown-800"><?= $category->title; ?></label>
    </div>
<?php endforeach; ?>

I hope this helps you!

  • Like 2
Link to comment
Share on other sites

It doesn't look like you're actively using a ProcessWire Fieldtype for generating or storing the values of your checkboxes (upon/after submit), and that you're manually creating them instead (which is fine, and more often expected on the frontend anyhow), so that means the checked() method won't do you any good.

@Mirox has the right idea. In that example, the value of $selectedCategories likely came from the ProcessWire API for inputs: $input->get->category.

Be sure to read over security precautions/implications when dealing with user input, and properly sanitizing it. ?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...