When building for WordPress, AJAX is a term which we hear very often, this blog shows how to implement a autocomplete search tailored to a custom post type meta box using WordPress AJAX.
Registering the Custom Post Type
Firstly, we need to define our custom post types to make query against. Here, we will use two post types— my_event and my_event_type. We can register these post types using the register_post_type()
function.
function my_event_post_type() { register_post_type('my_event', array( 'labels' => array( 'name' => 'Events', 'singular_name' => 'Event', ), // Use block editor 'show_in_rest' => true, 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments', 'revisions' ), 'public' => true, 'show_ui' => true, )); } add_action('init', 'my_event_post_type'); function my_event_types_post_type() { register_post_type('my_event_types', array( 'labels' => array( 'name' => 'Event Types', 'singular_name' => 'Event Type', ), 'show_in_rest' => true, // Ensure compatibility with the block editor. 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments', 'revisions' ), 'public' => true, 'show_ui' => true, )); } add_action('init', 'my_event_types_post_type');
Adding the Meta Box
Now that we have custom post types set up we need to allow users to select event types when editing a post.
function meta_box_event_types() { add_meta_box( 'event-meta-types', 'Event Types', 'event_types_meta_box_html', 'my_event', 'side', ); } add_action( 'add_meta_boxes', 'meta_box_event_types' );
Next, we’ll need the HTML for the event type input field inside the meta box.
function event_types_meta_box_html(WP_Post $post) { ?> <div> <label for="my-event-type">Event Type(s)</label><br> <input type="text" id="my-event-type" name="my-event-type" value="" /> <div id="autocomplete-suggestions" style="display:none;"></div> <ul id="selected-event-types" style="list-style-type: none; padding: 0;"></ul> <input type="hidden" id="selected-event-types-json" name="selected-event-types-json" value="" /> </div> <?php }
Handling the Autocomplete AJAX Request
When a user starts typing in the input field, we need to fetch relevant event types based on the search query. We can use WordPress’s AJAX functionality for this.
add_action( 'wp_ajax_fetch_autocomplete_suggestions', 'fetch_autocomplete_suggestions' ); function fetch_autocomplete_suggestions() { if ( isset($_GET['query']) && !empty($_GET['query']) ) { $search_query = sanitize_text_field( $_GET['query'] ); $args = [ 'post_type' => 'my_event_types', 'posts_per_page' => 10, 's' => $search_query, ]; $query = new WP_Query($args); $results = []; if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); $results[] = [ 'name' => get_the_title(), 'id' => get_the_ID(), ]; } wp_reset_postdata(); } echo json_encode($results); } wp_die(); }
Enqueueing the JavaScript
We need to add JavaScript to handle the user input then send an AJAX request and finally display the suggestions.
function enqueue_event_types_script( $hook ) { if ( 'post.php' === $hook || 'post-new.php' === $hook ) { wp_enqueue_media(); wp_enqueue_script( 'my-event', plugin_dir_url( __FILE__ ) . 'autocomplete.js', array(), '1.0', array() ); } } add_action( 'admin_enqueue_scripts', 'enqueue_event_types_script' );
Frontend Javascript
Finally, we need write the Javascript on frontend for handling the search input, displaying autocomplete suggestions, and adding/removing selected event types.
document.addEventListener('DOMContentLoaded', function () { document.getElementById('my-event-type').addEventListener('input', function() { let searchTerm = this.value; if (searchTerm.length > 2) { fetchAutocompleteSuggestions(searchTerm); } else { document.getElementById('autocomplete-suggestions').style.display = 'none'; } }); function fetchAutocompleteSuggestions(query) { fetch(ajaxurl + '?action=fetch_autocomplete_suggestions&query=' + query) .then(response => response.json()) .then(data => { let suggestionsBox = document.getElementById('autocomplete-suggestions'); suggestionsBox.innerHTML = ''; // Clear previous suggestions if (data.length > 0) { data.forEach(type => { let div = document.createElement('div'); div.textContent = type.name; div.addEventListener('click', function() { addSelectedType(type); suggestionsBox.style.display = 'none'; document.getElementById('my-event-type').value = ''; // Clear input }); suggestionsBox.appendChild(div); }); suggestionsBox.style.display = 'block'; } else { suggestionsBox.style.display = 'none'; } }); } function addSelectedType(type) { let selectedTypesList = document.getElementById('selected-event-types'); let selectedTypesJsonInput = document.getElementById('selected-event-types-json'); let listItem = document.createElement('li'); listItem.textContent = type.name; listItem.dataset.id = type.id; let removeBtn = document.createElement('button'); removeBtn.textContent = 'Remove'; removeBtn.classList.add('remove-event-type'); removeBtn.addEventListener('click', function() { selectedTypesList.removeChild(listItem); updateSelectedTypesJson(); }); listItem.appendChild(removeBtn); selectedTypesList.appendChild(listItem); updateSelectedTypesJson(); } function updateSelectedTypesJson() { let selectedTypesList = document.getElementById('selected-event-types').children; let selectedTypes = []; Array.from(selectedTypesList).forEach(function(item) { selectedTypes.push({ id: item.dataset.id, name: item.textContent.replace('Remove', '').trim() }); }); document.getElementById('selected-event-types-json').value = JSON.stringify(selectedTypes); } });
Additionally, debounce function can be incorporated to avoid making too many requests to the backend.
Conclusion
With these steps, we’ve successfully implemented a custom autocomplete search for selecting event types in WordPress using AJAX.
This approach can be extended to any other custom post type or taxonomies and we can tweak it to fit different requirements.
Leave a Reply