Yes, there is a built-in WordPress function you can use to render a list of checkboxes (or simply, checklist) which then allows the user to select multiple terms, and the function is [`wp_terms_checklist()`](https://developer.wordpress.org/reference/functions/wp_terms_checklist/). However, the function only works for users who have the capability/permission to assign terms to a post, so you'd need to create your own function for public (i.e. front-end or non-admin side) use. And you can try my custom function below which uses the [`Walker_Category_Checklist`](https://core.trac.wordpress.org/browser/tags/5.6.2/src/wp-admin/includes/class-walker-category-checklist.php#L19) class which is the same class that's used by `wp_terms_checklist()` to build the terms checklist. But do take note of these conditions: 1. You'd need to style the checklist on your own, e.g. to remove the bullet next to each checkbox. (Because the checkbox is in an `li` element.) 2. The checkboxes `name` is in the form of `tax_input[<taxonomy>][]`, e.g. `<input type="checkbox" name="tax_input[salary_level][]"`. So you can't simply use `get_query_var()` to get the selected terms (which each is a term ID). 3. You'd need to hook on [`pre_get_posts`](https://developer.wordpress.org/reference/hooks/pre_get_posts/) to make sure the selected terms are being included in the search query (i.e. its SQL statement). ## The Code * In your theme's `functions.php` file, add this custom function I mentioned above: ```php /* * Based on wp_terms_checklist(), but this is simpler and without the very first parameter * (i.e. $post_id). * * @param array $args An array of arguments. See the second parameter for wp_terms_checklist() * for the list of arguments, but 'descendants_and_self' and 'walker' are * not included in this function. * * @return string|false $output HTML list of checkbox elements. false on get_terms() error. */ function wpse_384435_checklist( array $args ) { require_once ABSPATH . 'wp-admin/includes/class-walker-category-checklist.php'; $terms = get_terms( array( 'taxonomy' => isset( $args['taxonomy'] ) ? $args['taxonomy'] : 'category', 'get' => 'all', ) ); if ( is_wp_error( $terms ) || empty( $terms ) ) { return false; } $walker = new Walker_Category_Checklist; $output = $walker->walk( $terms, 0, $args ); if ( ! isset( $args['echo'] ) || $args['echo'] ) { // this means echo is default echo $output; } return $output; } ``` * Also in the functions file, add this which does the point #3 above: ```php add_action( 'pre_get_posts', 'my_search_pre_get_posts' ); function my_search_pre_get_posts( $query ) { // We're altering the MAIN query args only on search result pages. if ( is_admin() || ! is_search() || ! $query->is_main_query() ) { return; } // For other taxonomies, just add the slug to the $taxonomies array below. $taxonomies = array( 'salary_level', 'jobs_categories' ); $tax_input = isset( $_GET['tax_input'] ) ? (array) $_GET['tax_input'] : array(); $tax_query = (array) $query->get( 'tax_query' ); $set_tax_query = false; foreach ( $taxonomies as $taxonomy ) { $selected_cats = ( ! empty( $tax_input[ $taxonomy ] ) ) ? wp_parse_id_list( $tax_input[ $taxonomy ] ) : array(); if ( ! empty( $selected_cats ) ) { $tax_query[] = array( 'taxonomy' => $taxonomy, 'terms' => $selected_cats, ); $set_tax_query = true; } } if ( $set_tax_query ) { $query->set( 'tax_query', $tax_query ); } } ``` * And then in your `form`, replace the `wp_dropdown_categories()` part with this: (for other taxonomies, you can just copy-paste-edit the same code below) ```php $taxonomy = 'salary_level'; $tax_input = isset( $_GET['tax_input'] ) ? (array) $_GET['tax_input'] : array(); $selected_cats = ( ! empty( $tax_input[ $taxonomy ] ) ) ? wp_parse_id_list( $tax_input[ $taxonomy ] ) : array(); echo '<div><label>Filter by Salary Bands:</label>'; wpse_384435_checklist( array( 'taxonomy' => $taxonomy, 'selected_cats' => $selected_cats, 'checked_ontop' => false, ) ); echo '</div>'; ``` PS: Be sure to use the correct *taxonomy slugs*! :)