fbpx

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>Code language: HTML, XML (xml)

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; ?>Code language: HTML, XML (xml)

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.

Updated Answer

Back in 2019, the solution published here included some filters to add custom variables to the WP_Query object. This worked quite well, but was, in retrospect, overkill.

FacetWP maintains a global PHP singleton with most of the information you could ever want attached to it, including whether or not any facets are activated. Here’s how you can use that in your own code:

<?php 

if(have_posts()) : 
	echo '<div class="row">';
	while(have_posts()) : the_post();

                // Checking our custom query arg here
		if(function_exists('FWP') && !FWP()->is_filtered): ?>
			<div class="col">
				<p class="text-center mt-3">Not faceting content...</p>
			</div>
			<?php 
                        // Short-circuit the while loop
                        break;
		endif; ?>
		<div class="col col-lg-4">
			<?php the_title(); ?>
		</div>
		<?php 
	endwhile; 
	echo '</div>';
else:
	echo 'No results!';
endif;


Code language: HTML, XML (xml)

Continue reading for a more do-it-yourself solution, plus how to include facet information on the WP_Query object.

The Old Answer

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 );Code language: PHP (php)

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;Code language: HTML, XML (xml)

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 );Code language: PHP (php)

Comments

One response to “Hide WordPress Query Results When FacetWP Facets are Empty”

  1. This was exactly what I was looking for. Thanks a lot for posting it.

Leave a Reply

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