Hide WordPress Query Results When FacetWP Facets are Empty

FacetWP diamond image

I’ve recently been diving into FacetWP as a tool for getting down and dirty with post filtering in WordPress. I’ve used Toolset Views in the past, and I’m not deep enough to say I have a favorite. But I have enjoyed that FacetWP, by and large, lets me bring my own templates to the party from within the theme. If there’s one thing I hate, it’s writing code in the WordPress admin.

In this particular use case, I had a collection of facets to narrow the results of a listing of products on the website. I needed to display something other than the unfiltered (unfaceted) query results if a user hadn’t selected any facets. Something like this:

A gif of removing a FacetWP selection and getting a unique message in response.
The desired result. With facets selected, we see products that match our narrowing filters. Turning off all facets, however, should show a special no-facets-active message. There’s definitely a typo in that heading, but you get the idea.

Even though the default query returns results, I don’t want to display them if no facets have been selected.

First, let’s take a look at how we’ve implemented FacetWP in this case. I had shortcodes to output my facets:

<div class="pt-4 px-3 mt-n5" id="accordion"> <div class="h1 text-center mb-4">Find Your Product</div> <?php $facets = [ 'accordion_who_is_it_for', 'accordion_series', ]; foreach($facets as $facet) { echo do_shortcode('[facetwp facet="' . $facet . '"]'); } ?> </div>

Then I wrote my own query and template. Documentation on the facetwp query argument can be found on the FacetWP website.

<?php $productQuery = new WP_Query([ 'post_type' => 'product', 'facetwp' => true, 'tax_query' => [ [ 'taxonomy' => 'product_cat', 'terms' => [184], ] ], ]); if($productQuery->have_posts()) : echo '<div class="row">'; while($productQuery->have_posts()) : $productQuery->the_post(); <div class="col col-lg-4"> <?php the_title(); ?> </div> <?php endwhile; echo '</div>'; else: echo 'No results!'; endif; ?>

Given this query, if there are any products on the site that match this default taxonomy query, this loop will display them. We need to disable that unless a user has selected some facets. Fortunately, FacetWP has some great filters we can take advantage of to add a custom query argument:

<?php // Add query arg if FacetWP is faceting a query add_filter( 'facetwp_query_args', function( $query_args, $class ) { // Merge all selected values from all applied facets // And see if it's empty if( !empty( array_merge([], ...array_column( $class->facets, 'selected_values' ) ) ) ) { $query_args['has_facets'] = true; } return $query_args; }, 10, 2 );

What this piece of code does is glob together the selected values from all facets that may be running on a query, and if that array is anything but empty, it adds a query argument we can test for later to know that the user has, in fact, activated some facets.

Because of how FacetWP handles hot reloading the loop content, we need to start the loop no matter what. We’ll have to short-circuit it rather than skip it altogether. Let’s check out the updated logic to handle this situation:

<?php // ... if($productQuery->have_posts()) : echo '<div class="row">'; while($productQuery->have_posts()) : $productQuery->the_post(); // Checking our custom query arg here if(!$productQuery->get('has_facets')): ?> <div class="col"> <p class="text-center mt-3">Not faceting content...</p> </div> <?php // Short-circuit break; endif; ?> <div class="col col-lg-4"> <?php the_title(); ?> </div> <?php endwhile; echo '</div>'; else: echo 'No results!'; endif; ?>

With a little massaging, that turned into the end product above. Pretty neat, though I’m still not convinced the UX is great—how does a user simply view all the products? I imagine there are other scenarios where this would make a ton of sense, though, and I’m glad to have it under my belt.

Update: Expose Facets to the WP Query

Sometimes it may be valuable to know not just whether or not any facets were selected, but if specific facets were selected. The above filter can easily be updated to expose all the selected facets to the WP_Query object for evaluation later:

<?php // Add query arg if FacetWP is faceting a query add_filter( 'facetwp_query_args', function( $query_args, $class ) { // Merge all selected values from all applied facets $facets = array_merge( [], ...array_column( $class->facets, 'selected_values' ) ); // And see if it's empty if( !empty( $facets ) ) { $query_args['facets'] = $facets; $query_args['has_facets'] = true; } return $query_args; }, 10, 2 );

Are You a Do-It-Yourself WordPress-er?

If you aren't ready to invest in Sterner Stuff, I've got something for you! Check out my new (and free) WordPress for Small Business Owners email course!

Leave a reply

Your email address will not be published. Required fields are marked *