I'm on wordpress and I created a search filter shortcode which user can select province and show towns on another html select base on province and when user select town, in another html select it must be billboard(s) in each of these three stages when form submitted result must be related billboard(s) base on selects.
provinces are the parent taxonomy
towns are the child of province taxonomy
billboard(s) are the posts
note that admin may just check the town(child) tax or may check both province(parent) and town(child) on each post; It must works well on both ways.
In my code I create basic search ajax that till now just can select posts(billboard) and it show that post with ajax or search in input that post
this is my code so far:
<?php
/**
* functions template
*
* @package Environmental Ads
*/
function en_ads_scripts()
{
wp_enqueue_style('en_ads_css', get_theme_file_uri() . '/assets/css/en-ads.css');
wp_enqueue_script('en_ads_ajax_filter_search', get_theme_file_uri() . '/assets/js/en-ads.js', array(), '1.0', true);
wp_localize_script('en_ads_ajax_filter_search', 'ajax_url', admin_url('admin-ajax.php')); //en_ads_ajax_filter_search must be like en-ads.js and used in it
}
// Shortcode: [en_ads_shortcode]
add_shortcode('en_ads_shortcode', 'en_ads_search_structure');
function en_ads_search_structure()
{
en_ads_scripts();
ob_start(); ?>
<div id="post-ajax-filter-search">
<form action="" method="get">
<input type="text" name="search" id="ajax-input-search" placeholder="">
<div class="search-option__list">
<?php
$searchFieldsQuery = get_posts(array(
'post_type' => 'en-ads',
'post_status' => 'publish',
'order' => 'ASC',
'posts_per_page' => -1,
));
if ($searchFieldsQuery) {
?>
<div class="search-option__item">
<label for="enProvince" class="search-option__item--label"> Province</label>
<select name="enProvince" id="enProvince" class="search-option__item--select">
<option value="">All Province</option>
<?php //must query Province Here?>
<?php wp_reset_query(); ?>
</select>
</div>
<div class="search-option__item">
<label for="enTown" class="search-option__item--label">Town</label>
<select name="enTown" id="enTown" class="search-option__item--select">
<option value="">All Towns</option>
<?php //must query towns that related to province ?>
<?php wp_reset_query(); ?>
</select>
</div>
<div class="search-option__item">
<label for="billboard" class="search-option__item--label">Billboard</label>
<select name="billboard" id="billboard" class="search-option__item--select">
<option value="">All Billboards</option>
<?php foreach ($searchFieldsQuery as $sfq) {
//this query should show the posts that related to province and town taxonomy
?>
<option value="<?php echo $sfq->post_title; ?>"><?php echo $sfq->post_title; ?></option>
<?php } ?>
<?php wp_reset_query(); ?>
</select>
</div>
<?php } ?>
</div>
<input type="submit" id="ajax-submit" name="submit" value="search">
</form>
<ul id="ajax_filter_search_results"></ul>
</div>
<?php
return ob_get_clean();
}
// Ajax Callback
add_action('wp_ajax_en_ads_ajax_filter_search', 'en_ads_ajax_filter_search_callback'); //wp_ajax_{js action}
add_action('wp_ajax_nopriv_en_ads_ajax_filter_search', 'en_ads_ajax_filter_search_callback'); //wp_ajax_nopriv_{js action}
function en_ads_ajax_filter_search_callback()
{
header("Content-Type: application/json");
$meta_query = array('relation' => 'AND');
if (isset($_GET['enProvince'])) {
$enProvince = sanitize_text_field($_GET['enProvince']);
$meta_query[] = array(
'key' => 'f_standby_rating_kva',
'value' => $enProvince,
'compare' => '='
);
}
if (isset($_GET['enTown'])) {
$enTown = sanitize_text_field($_GET['enTown']);
$meta_query[] = array(
'key' => 'f_prime_rating_kva',
'value' => $enTown,
'compare' => '='
);
}
$args = array(
'post_type' => 'en-ads',
'posts_per_page' => -1,
'meta_query' => $meta_query
);
if (isset($_GET['search'])) {
$search = sanitize_text_field($_GET['search']);
$search_query = new WP_Query(array(
'post_type' => 'en-ads',
'posts_per_page' => -1,
'meta_query' => $meta_query,
's' => $search
));
} else {
$search_query = new WP_Query($args);
}
if ($search_query->have_posts()) {
$result = array();
while ($search_query->have_posts()) {
$search_query->the_post();
$result[] = array(
"id" => get_the_ID(),
"billboard" => get_the_title(),
"permalink" => get_permalink(),
"enProvince" => 'must get the exact billboard province to use in js',
"enTown" => 'must get the exact billboard town to use in js',
"poster" => wp_get_attachment_url(get_post_thumbnail_id(get_the_ID()), 'full')
);
}
wp_reset_query();
echo json_encode($result);
} else {
// no posts found
}
wp_die();
}
And this is my js:
$ = jQuery;
var pafs = $("#post-ajax-filter-search");
var pafsForm = pafs.find("form");
pafsForm.submit(function (e) {
e.preventDefault();
if (pafsForm.find("#ajax-input-search").val().length !== 0) {
var search = pafsForm.find("#ajax-input-search").val();
}
if (pafsForm.find("#billboard").val().length !== 0) {
var search = pafsForm.find("#billboard").val();
}
if (pafsForm.find("#enProvince").val().length !== 0) {
var enProvince = pafsForm.find("#enProvince").val();
}
if (pafsForm.find("#enTown").val().length !== 0) {
var enTown = pafsForm.find("#enTown").val();
}
var data = {
action: "en_ads_ajax_filter_search",
search: search,
enProvince: enProvince,
enTown: enTown,
};
console.log(data);
$.ajax({
url: ajax_url,
data: data,
success: function (response) {
pafs.find("ul").empty();
//console.log(response);
if (response) {
for (var i = 0; i < response.length; i++) {
var html = `
<li id="ad-${response[i].id}" class="ad-item">
<a href="${response[i].permalink}" title="${response[i].billboard}" class="ad-item__image--link">
<img src="${response[i].poster}" alt="${response[i].billboard}" class="ad-item__image--img">
</a>
<div class="ad-item__info">
<h4 class="ad-item__info--billboard">Billboard: ${response[i].billboard}</h4>
<p class="ad-item__info--province">Province: ${response[i].enProvince}</p>
<p class="ad-item__info--town">Town: ${response[i].enTown}</p>
<a href="${response[i].permalink}" title="${response[i].billboard}" class="ad-item__info--more">
more Info <i class="fas fa-angle-left" aria-hidden="true"></i>
</a>
</div>
</li>
`;
pafs.find("#ajax_filter_search_results").append(html);
}
}
// else {
// var html = `
// <li class='no-result'>Billboard Not Found</li>
// `;
// pafs.find("ul").append(html);
// }
},
error: function (jqXHR, exception) {
pafs.find("#ajax_filter_search_results").empty();
if (jqXHR.status === 0) {
var errorText = "error";
} else if (jqXHR.status == 404) {
var errorText = "error";
} else if (jqXHR.status == 500) {
var errorText = "error";
} else if (exception === "parsererror") {
var errorText = "error";
} else if (exception === "timeout") {
var errorText = "Time out error";
} else if (exception === "abort") {
var errorText = "error";
} else {
var errorText = "error";
}
var html = `
<li class='no-result'>${errorText}</li>
`;
pafs.find("#ajax_filter_search_results").append(html);
},
});
});
wp_reset_query
( that function should only be sued withquery_posts
, aka never, did you meant o usewp_reset_postdata()
? ) Also the calls towp_reset_query
in your shortcode are completely unnecessary as the code never sets the current post and does not usequery_posts
so there is nothing to reset