I’m trying to figure out a way to reset the selected option of one or more in a series of three dropdowns; this is in a function that reloads a page with certain URL parameters that show the filtered results via the SQL query at the bottom of the function. Explanation and examples below.
There are three dropdowns (Country, City and Delivery) that filter database results returned via URL.
Each filter works in conjunction with the others. I can reset one, two or all three filters by simply reloading example.com/directory/
.
But what I really want to do is be able to reset each filter individually and reload the URL with the parameters for the remaining filter(s).
Examples:
If I use the first filter for the country USA, the URL that loads is
example.com/directory/?my_country=USA
If I also filter for Alaska in the second filter, the URL reloads and is
example.com/directory/?my_country=USA&my_state=AK
How can I reset the Country filter and then reload example.com/directory/?my_state=AK
?
Or, to reset State when all three filters are used, i.e.
example.com/program-directory/?my_country=USA&my_state=AK&my_delivery=Classroom
how do I reset State to return
example.com/program-directory/?my_country=USA&my_delivery=Classroom
I can’t use Reset select value to default because I need to reload the specific URL with parameters when a filter is reset.
What’s the best approach?
• Can I exclude the filter being reset from $sql_parts
by using PHP?
• Or use jQuery to exclude the reset filter(s) and reload the page with URL parameters of the remaining filters?
• Other possibilities?
Yes, there is a seeming conflict between selecting state and country, as CBroe pointed out, but these three filters are for illustration only, as there are more then three IRL.
PHP:
<div class="filter-level">Country:</div>
<?php
$country = array(
'Australia' => 'Australia',
'China' => 'China',
'USA' => 'USA',
// other countries omitted for clarity
);
echo '<select id="my_country" name="my_country">';
echo '<option value="" selected disabled hidden>Select Country</option>';
foreach ( $country as $key => $value ) {
$checked_modifier = '';
if ( ! empty( $_REQUEST['my_country'] ) && $key == $_REQUEST['my_country'] ) {
$checked_modifier = ' selected';
}
echo '<option value="' . $key . '"' . $checked_modifier . '>'. $value .'</option>';
}
echo '</select>';
?>
<div class="filter-button"><input type="submit" class="filter-submit" value="Filter Country"></div>
<div class="reset-filter-button"><input type="submit" class="reset-filter" value="Reset Country"></div> <!-- Reset -->
<div class="filter-level">State:</div>
<?php
$state = array(
'AK' => 'Alaska',
'AL' => 'Alabama',
'AB' => 'Alberta',
// other states omitted for clarity
);
echo '<select id="my_state" name="my_state">';
echo '<option value="" selected disabled hidden>Select State/Province</option>';
foreach ( $state as $key => $value ) {
$checked_modifier = '';
if ( ! empty( $_REQUEST['my_state'] ) && $key == $_REQUEST['my_state'] ) {
$checked_modifier = ' selected';
}
echo '<option value="' . $key . '"' . $checked_modifier . '>'. $value .'</option>';
}
echo '</select>';
?>
<div class="filter-button"><input type="submit" class="filter-submit" value="Filter State/Province"></div>
<div class="reset-filter-button"><input type="submit" class="reset-filter" value="Reset State"></div> <!-- Reset -->
<div class="filter-level">Delivery:</div>
<?php
$delivery = array(
'Classroom' => 'Classroom Only',
'Online Only' => 'Online Only',
'Hybrid' => 'Hybrid',
);
echo '<select id="my_delivery" name="my_delivery">';
echo '<option value="" selected disabled hidden>Select Delivery</option>';
foreach ( $delivery as $key => $value ) {
$checked_modifier = '';
if ( ! empty( $_REQUEST['my_delivery'] ) && $key == $_REQUEST['my_delivery'] ) {
$checked_modifier = ' selected';
}
echo '<option value="' . $key . '"' . $checked_modifier . '>'. $value .'</option>';
}
echo '</select>';
?>
<div class="filter-button"><input type="submit" class="filter-submit" value="Filter Delivery"></div>
<div class="reset-filter-button"><input type="submit" class="reset-filter" value="Reset Delivery"></div> <!-- Reset -->
</form>
<?php
}
}
function directory_widget_filter_sql_parts( $sql_parts, $levels, $s, $pn, $limit, $start, $end, $order_by, $order ) {
global $wpdb;
if ( ! empty( $_REQUEST['my_country'] ) ) {
$sql_parts['JOIN'] .= " LEFT JOIN $wpdb->usermeta um_my_country ON um_my_country.meta_key = 'my_country' AND u.ID = um_my_country.user_id ";
$sql_parts['WHERE'] .= " AND um_my_country.meta_value = '" . sanitize_text_field( $_REQUEST['my_country'] ) . "' ";
}
if ( ! empty( $_REQUEST['my_state'] ) ) {
$sql_parts['JOIN'] .= " LEFT JOIN $wpdb->usermeta um_my_state ON um_my_state.meta_key = 'my_state' AND u.ID = um_my_state.user_id ";
$sql_parts['WHERE'] .= " AND um_my_state.meta_value = '" . sanitize_text_field( $_REQUEST['my_state'] ) . "' ";
}
if ( ! empty( $_REQUEST['my_delivery'] ) ) {
$sql_parts['JOIN'] .= " LEFT JOIN $wpdb->usermeta um_my_delivery ON um_my_delivery.meta_key = 'my_delivery' AND u.ID = um_my_delivery.user_id ";
$sql_parts['WHERE'] .= " AND um_my_delivery.meta_value = '" . sanitize_text_field( $_REQUEST['my_delivery'] ) . "' ";
}
return $sql_parts;
}
3
Answers
You could have one Filter button at the end of the form and Reset buttons that set corresponding lists to their empty values, but do not reload the page. This will submit all the filters at once, but if some or all of the lists are reset, their corresponding values will be empty (worst case:
example.com/program-directory/?my_country=&my_state=&my_delivery=
).Something like this:
Use js in a similar way to the following:
Then handle reset filter in PHP:
Introduction
Any change that we may apply here needs to be compatible with other changes. I will create separate sections for the solution, but note, the codes I’m having are untested, so it’s possible that there will be typos or minor mistakes on my part, so please focus on the idea and be patient with any mistakes that I may make. I’m happy to fix them if I get constructive criticism in the comment-section. I also welcome down-votes as long as they are paired with a comment that explain what’s wrong and allow me to improve my answer.
Make your select handling abstract
You have the same code being applied thrice in the example, so if you are to implement a fundamental change, you will always need to apply it thrice. I strongly advise you to make a function out of it to handle the common pattern and the differences would be handled based on parameters:
Note that instead of echoing the template right away, I’m generating a template and returning it, so, when you use the function, you will be able to
echo
it right away.Usage of your function
or you can embed it into further templates, like
function for SQL parts
You are repeating your logic for SQL parts as well. Let’s make a function of it:
Again, if you have to perform fundamental changes, you will have a largely easy time doing so.
Simplifying left join generation
Here I’m assuming that
$levels
is an array of strings with the name of the levels, like my_country. If the names are slightly different, then you need to make a conversion of names as well.How to make it work properly
You will need to make sure that these selects, resets and stuff will use the same feature on the client-side rather than repeating it. Either put them all into a
form
or to create JS infrastructure for it.Since you did not even want to have a parameter with default values in the URL, I will assume you want the JS infrastructure here. So make sure you do not send a form, but you do it via Javascript.
Filter buttons
We loop the items having the class of
filter-submit
and add aclick
handler to each of them which will go through theselect
tags having their id among a set we specified and if they have avalue
of interest, we push it into ourparams
, then convert this array into a string and redirect to the page, either without parameters, if everything was empty, or, redirect to the page along with parameters otherwise.Resetting
So, for each reset button, we create a click event handler, which will find their parent and from there, we set the selector inside the parent to have an empty string as a value and click on the filter submit