It's hard to figure out your real world problem but I will try my best:
Let me visualize what you're trying to archive:
jQuery(document).ready(function($){
"use strict";
var parentSelectBox = $("#parent-select-box");
parentSelectBox.change(function(e){
e.preventDefault();
var childForm = $("#child-select-box"), parentTermID = parentSelectBox.val();
var terms = {
"1": [
{id: 11, name: "Child Term 1.1"},
{id: 12, name: "Child Term 1.2"}
],
"3": [
{id: 21, name: "Child Term 2.1"},
{id: 22, name: "Child Term 2.2"}
]
};
childForm.empty(); // Remove all old options.
childForm.append('<option disabled selected>--Select a child term--</option>');
if (terms.hasOwnProperty(parentTermID)) {
var childTerms = terms[parentTermID];
$.each(childTerms, function(){ // Add new options.
childForm.append('<option value="' + this.id + '">' + this.name + '</option>');
});
} else {
console.log('There are no child terms.');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="parent-from" class="form parent" method="post">
<select id="parent-select-box" name="parent-term">
<option disabled selected>--Select a parent term--</option>
<option value="1">Parent Term 1</option>
<option value="2">Parent Term 2</option>
</select>
</form>
<form id="child-form" class="form child" method="get">
<select id="child-select-box" name="child-term">
<option disabled selected>--Select a child term--</option>
<option value="3">Default Child Term 3</option>
<option value="4">Default Child Term 4</option>
</select>
</form>
As you can see, after you selected the Parent Term 1
in the first select box, in the second select box, the child terms (Child Term 1.1
and Child Term 1.2
) are populated automatically. If you have selected the Parent Term 2
, you will see There are no child terms.
on the console.
But it's plain HTML/JS, we have to incorporate it into WordPress:
First of all, I suppose that you know how to use AJAX to retrieve data in WordPress.
The first select box is a filter to retrieve data for the second select box. We will use AJAX base on .change()
event of the parent select box:
jQuery(document).ready(function($){
"use strict";
var parentSelectBox = $("#parent-select-box");
parentSelectBox.change(function(e){ // .change()
e.preventDefault();
var parentTermID = parentSelectBox.val();
// {
// Some code with AJAX to get child terms base on `parentTermID` here.
// }
// Now, suppose `terms` is AJAX response.
if ($.isEmptyObject(terms)) { // There're no child terms.
// Do something...
} else {
// Append them to the second select box.
}
});
});
For the second select box, I don't know about DOM structure of your document but I think we don't need AJAX. Use GET
method with .change()
event:
jQuery(document).ready(function($){
"use strict";
var childForm = $("#child-form"),
childSelectBox = $("#child-select-box");
childSelectBox.change(function(e){
e.preventDefault();
childForm.submit();
});
});
Now, right after user select a child term, child form will be submit automatically and append child-term
to the URL via GET
method. We will use this value with pre_get_posts
action to filter posts result:
add_action('pre_get_posts', function(\WP_Query $query) {
// If you're using main query, remember to check `$query->is_main_query()` as well.
if ( isset($_GET['child-term']) && !empty($_GET['child-term']) ) {
$query->query_vars['tax_query'] = [
[
'field' => 'term_id',
'terms' => absint($_GET['child-term']),
'taxonomy' => 'city'
]
];
}
});
You may need to see taxonomy parameters for more info.