Liven up WordPress default search

Using AJAX are add some dynamic to a page where it used, in addition dynamic search more usability. About how to make it we talk in this article.

AJAX live search in WordPress

Problem: Need make dynamic output search results in WordPress.
Solution: resolve is very simple, all you need step by step follow to the next instruction.

Step 1: Make form on the need page:

<form id="search-form">
    <div class="form-group">
        <input type="search" name="q" id="search-query" placeholder="<?php _e( 'Search for...', 'domain-name' ); ?>" autocomplete="off" maxlength="64" tabindex="1">
        <span class="input-btn">
            <button class="btn btn-custom" type="submit" tabindex="-1"></button>
        </span>
    </div>
</form>
<ul id="data" class="data" tabindex="0"></ul>

Step 2: Make front-end handler for work with our form and AJAX. For example, we make folder js and put at here file script.js.

(function ( $ ) {
    $( document ).ready( function () {
        fetchData();
    } );

    function fetchData() {
	    var searchForm = $( '#search-form' );

	    if ( searchForm.length ) {
		    var minLengthSearchQuery = 3;

		    $( '#search-query' ).keyup( function () {
			    var value = $( this ).val();

                if ( value.length >= minLengthSearchQuery ) {
			        $.ajax( {
				        url: ajax.url,
				        type: 'post',
				        data: {
					        action: 'fetch_data',
					        keyword: value,
					        nonce: ajax.nonce,
				        },
				        success: function ( data ) {
					        $( '#data' ).show();
						    $( '#data' ).html( data );
				        }
			        } );
                } else {
                    $( '#data' ).empty();
                }
		    } );
	    }
    }
})
( jQuery );

Step 3: Make back-end handler. Open our functions.php file and put in next code.

<?php
....

define( 'TEMPLATE_DIRECTORY_URI', get_template_directory_uri() );
....

add_action( 'wp_enqueue_scripts', 'enqueue_scripts' );
	
function enqueue_scripts() {
...
    wp_deregister_script( 'jquery' ); // Disable default JQuery for WordPress
    wp_register_script( 'jquery', TEMPLATE_DIRECTORY_URI . '/js/jquery.min.js', [], null, 'in_footer' );
    wp_enqueue_script( 'jquery' ); // Enable our JQuery
    wp_enqueue_script( 'script', TEMPLATE_DIRECTORY_URI . '/js/script.js', [ 'jquery' ], null, 'in_footer' );
	wp_localize_script( 'script', 'ajax', [
	    'url' => admin_url( 'admin-ajax.php' ),
        'nonce' => wp_create_nonce( 'search-form-nonce' ),
	] );
}
...
if ( wp_doing_ajax() ) {
	add_action( 'wp_ajax_fetch_data', 'fetch_data' );
	add_action( 'wp_ajax_nopriv_fetch_data', 'fetch_data' );
}
	
function fetch_data() {
	check_ajax_referer( 'search-form-nonce', 'nonce' );
		
	$sanitize_keyword = tag_escape( $_POST['keyword'] );
	$keyword = isset( $sanitize_keyword ) ? $sanitize_keyword : '';
		
	if ( ! empty( $keyword ) && strlen( $keyword ) >= 3 ) :
		$args = [
			'post_type' => 'post',
			'post_status' => 'publish',
			'fields' => 'ids',
			'no_found_rows' => 'true',
			'posts_per_page' => -1,
			's' => $keyword,
		];
			
		$query = new WP_Query( $args );
		
		if ( $query->have_posts() ) :
			while ( $query->have_posts() ): $query->the_post(); ?>
                <li class="success result" tabindex="1">
                    <a href="<?php echo esc_url( get_permalink() ); ?>"><?php the_title(); ?></a>
                </li>
			<?php endwhile;
		else : ?>
            <li class="error result"><?php _e( 'Sorry, but nothing matched your search criteria. Please try again with some different keywords.', 'domain-name' ); ?></li>
		    <?php 
        wp_reset_postdata();
		endif;		
	else : ?>
        <li class="error result"><?php _e( 'Oops, looks like we can\'t find properties that meet your requirements 🙁 Please, try to change the search query and give it another shot 🙂', 'domain-name' ); ?></li>
	<?php
	endif;
	wp_die();
}

That's all! 🙂 You need only add styles.

Sources:

  1. https://wordpress.stackexchange.com/questions/240138/ajax-live-search-for-post-title

Leave Comment

Your email address will not be published.