Jump to content
strandoo

Filtering with multiple check boxes

Recommended Posts

Hi all. I'm building a product search page with a filter consisting of selects and checkboxes. It's based on Ryan's excellent Skyscraper demo, but I'm trying to add multiple checkbox fieldtypes. I've got it working, but it's not very elegant and I'm sure there's a better way to do it.

Given the following checkboxes:
[x] Adidas (15)
[  ] Asics (10)
[x] Nike (20)

If only Adidas is checked, 15 shoes will be found; if both Adidas and Nike, 35 shoes will be found.

The form field:

foreach($pages->get("/brands/")->children() as $brand) {
   $selected = $brand->name == $input->whitelist->brand ? " checked='checked' " : "";
    echo "<label><input $selected type='checkbox' name='brand[]' value='{$brand->name}'> {$brand->title}</label>";
}

Here's what I've got for the select, based on the Skyscraper search:

$selector = '';
...
if($input->get->brand) {
    $brands = $input->get->brand;
    $selector .= "brand=";
    foreach($brands as $brand) {
        $value = $brand;
        $selector .= "$value|";
        $input->whitelist('brand', $value);
    }
    $selector .= ", ";
}
...
$selector = "template=product-page, limit=24, " . trim($selector, ", ");

This sort of works (although pagination doesn't work because I don't know how to do the whitelist part -- bonus question!). The correct results are returned, but an echo of the selector string looks weird: "template=product-page, limit=24, brand=adidas|nike| " (there's a trailing pipe character that I don't know how to remove).

Is there a better way to do this? Thanks in advance.

 

Share this post


Link to post
Share on other sites

you'd need to first change the brand selector to band.name, so it would look like brand.name=adidas|nike

i don't think the trailing pipe will affect anything, but you can remove it before you add the comma, using a rtrim.

Alternately you can use the new selector array syntax; The skyscrapers profile is probably really old and doesn't represent the latest and greatest advances and breakthroughs that the api has to offer. I would recommend to study this blog post:

https://processwire.com/blog/posts/processwire-3.0.13-selector-upgrades-and-new-form-builder-version/#building-a-selector-string-with-user-input-example

Share this post


Link to post
Share on other sites

Thanks, Macrura. I just read that post and I like the idea of using selectors as arrays. I might try that after I redo my code the 'normal' way. My script works as is (with out using brand.name) because my input IS the brand name, not the page id... if I understand correctly. But I see from that post that maybe I should use the ID and do as you suggest. After my original post, I used rtrim for something else then slapped my head for not trying it here. Then I just need to read up on whitelists... Cheers.

Share this post


Link to post
Share on other sites
57 minutes ago, strandoo said:

my input IS the brand name, not the page id... if I understand correctly.

maybe the selector engine is figuring it out based on whether it is an integer and then looking at the page name (if you are using page reference)

Share this post


Link to post
Share on other sites
9 hours ago, strandoo said:

Then I just need to read up on whitelists...

These topics may be useful:

 

  • Like 1

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By michelangelo
      Hello guys, I am building a sort of an archive. Relatively simple, although I have about 8000 records, each with 15 fields (text, int, images, url). I created a crude search system with a form (emulating the famous Skyscrapper example) to filter through the system. Everything works but it is quite slow... I have 2 questions which are related:

      1. How can I search through the database?
      2. What is a good practice to display many records like these?
      -----------------------------------------
      1. I am retrieving the results with
      $songs = $pages->findMany('template=nk-song'); Then I do a foreach to render them all. I am unsure if that is a good way. If I render all of them on the page, it creates thousands of divs with a bit of text, and this can take a while (10s-15s).
       
      2. This one is even worse :D as every time I retrieve my desired records with something like this:
      $page->find("field_to_search_through~=my_query_string") I get between 20 and 200, but when I render them I am creating iframes with YouTube videos and that can take up to 10s to finish. I "solved" it by only loading the iframes if they are in view with IntersectionObserver on the client-side. But I feel there is a more precise PHP / ProcessWire approach.
       
      Just to clarify, I started doing all of this custom rendering and querying because tools like ElasticSearch or SearchEngine were a bit complicated and I needed a simple to retrieve information and then display it in my own way.
      Thank you!
    • By snobjorn
      I have a website with multiple content types that I want to be accessible through search. I really like the live search on processwire.com, that sorts content types while typing. I tried to find the code to recreate this, with no luck. Does anyone know if this is jquery, specific jquery plugins, json/xml cached files, and what kind of PHP code is used? Any tip that point me in the right direction would be much apperciated.
      The search result listing seems fairly easy to create with sorting through parameters.
    • By Anders
      I want to allow full text search on my site. There is a very nice solution that comes right out of the box:
      $selector = "title|body~=$q, limit=50"; This works, but to make it even better I would want to give higher weight to pages where the search term occurs in the title, than if it just occurs in the body. After all, a page with the title "Wine from France" is probably the best match for the search "france wine". How do I accomplish this in ProcessWire?
      I can see three possible paths, but I am not very fond of any of them:
      Do a direct SQL query, circumventing the API, along these lines. But I would prefer to abstract away the database layout if at all possible. Use something like ElasticSearch, but to be honest that would be to complicated to set up and maintain in the long run. Make multiple lookups, first for matches in the title, then for matches in the body, and merge and sort in PHP. My suspicion is that this would get complicated quite quickly. For instance, how do you deal with a page that has two of the three search terms in the title and the third in the body? Is there a magic option four I should look into? Or are any of the above options better than the others? Any input is welcome!
    • By ngrmm
      I have a page with a table. Each table row has a page-reference field and a checkbox.
      The Page sends emails to all users (page-refrence->email-field) and change the value of the checkbox in a row to 1.
      It works with this:
      <?php // event ID fron url query $eventID = $input->get('eventID','int'); // get event-page $event = $pages->get($eventID); // config $fromEmail = $event->event_mail_from; $fromName = $event->event_mail_from_name; $emailSubject = $event->event_subject; // email html body ob_start(); include('./_inc/emailbody.inc'); $emailBody = ob_get_clean(); // make event-page editable $event->of(false); // loop through table and send out emails foreach($event->event_clients_list as $event_table_row) { // get client page $clientPage = $event_table_row->client_name; // get client email $clientEmail = $clientPage->email; // if client isn't invited yet (checkbox not checked) if($event_table_row->client_invited == '') { // send email $m = new WireMail(); $m->to($clientEmail); $m->from($fromEmail, $fromName); $m->subject($emailSubject); $m->bodyHTML($emailBody); $m->send(); // mark client as invited $event_table_row->client_invited = 1; $event->save('event_clients_list'); } } ?> But i have to use a variable in my emailbody.inc which i'm able to get in the table-loop.
      So i do the including of the body inside my loop. But this doesn't work anymore. Page sends out the emails but is unable to change the value of the checkbox.
      I get no errors!
      I'm using ProTable
      <?php // event ID fron url query $eventID = $input->get('eventID','int'); // get event-page $event = $pages->get($eventID); // config $fromEmail = $event->event_mail_from; $fromName = $event->event_mail_from_name; $emailSubject = $event->event_subject; // loop through table and send out emails foreach($event->event_clients_list as $event_table_row) { // get client page $clientPage = $event_table_row->client_name; // get client email $clientEmail = $clientPage->email; // email html body ob_start(); include('./_inc/emailbody.inc'); $emailBody = ob_get_clean(); // make event-page editable $event->of(false); // if client isn't invited yet (checkbox not checked) if($event_table_row->client_invited == '') { // send email $m = new WireMail(); $m->to($clientEmail); $m->from($fromEmail, $fromName); $m->subject($emailSubject); $m->bodyHTML($emailBody); $m->send(); // mark client as invited $event_table_row->client_invited = 1; $event->save('event_clients_list'); } } ?>  
    • By jds43
      Hello,
      I have a search page loosely based on Skyscrapers where I'm parsing a selector with options 'beds', 'bathrooms', 'size' fields. It is working well until I select 'Any' after I've run a search. This is where no results are returned (/?beds=&bathrooms=&size=&submit=). I want it to reset and show all results.
      I hope this isn't too vague.
       
×
×
  • Create New...