Selecting a Post using Post Title with the help of AJAX from Customizer – WordPress

I was working on one of my projects when suddenly I encountered a problem – Selecting a Single Post from the Customizer. Sure, there are many ways to do it, some of them including a drop-down including all the posts, manually entering the ID of a post by the user and extracting the post by selecting a category. While all of these methods work, I found that they lack a certain user-friendliness. The dropdown list of all the posts begins to struggle when the number of posts starts increasing. Being a user, I myself would not take the pain to find out the ID of a post and enter it in a field just to select it. Extracting the post from a selected category also seems a rather waste of resources considering a complete category has to be loaded. So, I decided to do something about it and came up with the solution of selecting a post using the post-title with the help of AJAX.

Before going into the code, I implore you to have a basic understanding of WordPress Theme Development. Also, a basic knowledge of jQuery is recommended.

Let’s start by creating a custom control. We’ll worry about the functionality later. Let’s make the control appear in the Customizer first. For the sake of this example, I am creating a new¬†section in which the control is going to be added. First. we’ll be creating a Custom Control. Paste the following code in functions.php –

 


if ( class_exists('WP_Customize_Control')) {
  class Example_Live_Search_Control extends WP_Customize_Control {
    /**
    * Render the Control's Content
    **/
    public function render_content() { ?>

      <span class="customize-control-title">
        <?php echo esc_html( $this->label ); ?>
      </span>

      <?php if($this->description){ ?>
        <span class="description customize-control-description">
          <!?php echo wp_kses_post($this->description); ?>
        </span>
      <?php } ?>
<input id="post_search" autocomplete="off" type="text" />link(); ?> value="<?php echo $this->value(); ?>">

<div id="search-results"></div>

<?php <br ?> }
}
}

 

Here, we have defined a custom control. It is like a regular input text field excep that it contains an additional div which is going to be used for displaying the search results.

Add the following code in your customizer.php file or wherever you have placed your code for Customizer Controls –

$wp_customize->add_section('example_section',
  array(
    'title' => __('AJAX Section', 'text-domain'),
    'priority' => 10,
  )
);

$wp_customize->add_setting('example_setting',
  array(
    'default' => '',
    'sanitize_callback' => 'example_sanitize_checkbox'
  )
);

$wp_customize->add_control(
  new Revive_Posts_Live_Search_Control(
    $wp_customize,
    'example_control',
      array(
        'label' => __('Select the Post','text-domain'),
        'description' => __('Enter the Post Title in the Text Field below', 'text-domain'),
        'settings' => 'example_setting',
        'section' => 'example_section'
      )
    )
);

function example_sanitize_checkbox( $input ) {
  if ( $input == 1 ) {
    return 1;
  } else {
    return '';
  }
}

 

Note that this code is going to be inside a function which, in turn, is going to be hooked to the ‘customize_register’ action.

The code above does nothing but add a control named ‘AJAX Control’ in a section named ‘AJAX Section’. Now, we should be having a custom control appearing in the Customizer.

 

 

But right now, it is just a simple text field and nothing more. To add functionality to the text field and make it a Live Search Tool, we are going to go towards AJAX.

 

Add the following code in functions.php –

/**
*	JS for the Customizer Controls
**/
function example_customize_control_js() {

    wp_enqueue_script( 'example_customizer_control_js', get_template_directory_uri() . '/js/customize-control.js', array(), 15382068, true );

}
add_action( 'customize_controls_enqueue_scripts', 'example_customize_control_js', 99);

 

Here, we have enqueued a file named customize-control.js present in the js folder in the theme directory. This file is responsible for creating all the magic.

Open this file and add the following code to it –

jQuery(document).ready(function() {
  jQuery( '#post_search' ).on( 'input', function() {

    var titleInput = jQuery( this ).val();

    if ( titleInput === '' ) {
      jQuery(this).html('');
      return;
    }

    data = {
      action: 'post_title_list',
      post_title: titleInput,
    }

    jQuery.post(ajaxurl, data, function( response ) {
      if ( response ) {
        jQuery('#search-results').html( response );
      }
    });
  });
});

 

Let’s go through this code. Initially, the text div ( ‘#post-search’) is checked for any change in content by binding the ‘input’ event to the input text box. That value is stored in the titleInput variable.
The input field is checked. If it is empty, the value of the text box is cleared.
If the text box is not empty, we get into AJAX. Here, we create a ‘data’ object in which properties which are to be sent to the server are stored. Here, we have stored two properties in this object – ‘action’ and ‘post_title’. ‘post_title’ stores the current value of the Input text box while ‘action’ stores an arbitrary value exclusive to the AJAX call. This ‘action’ property is kinda important, we will come back to it later.

Then, we use the jQuery.post() method to interact with the server. There are two main mmethods used to interact with server during AJAX call – get() and post(). I leave it to you to understand the difference between the two.
The jQuery.post() method accepts 2 arguments and a callback function. The first variable is the URL of the file to be accessed. In this case, we have used ‘ajaxurl’, it is a predefined value for URL if we are using it in back-end. Note that if we are using AJAX on front-end, we will have to specify the URL of the ‘admin-ajax.php’ file present in the core of WordPress. This ‘admin-ajax.php’ file is responsible for performing any and all AJAX calls in WordPress. The second argument is the data that is sent to the server which we have defined earlier. The third argument is the callback function. In this function, we use the data that is fetched from the server. Here, we can see that the empty div ‘#search-results’ is filled with the response from the server.

 

Now, Let’s get back to functions.php. Add the following code to functions.php –

<code>
/**
*	AJAX Functionality for Post Search in Customizer
**/</code>

add_action( 'wp_ajax_post_title_list', 'revive_ajax_post_title_list');

function revive_ajax_post_title_list() {

  $string = $_POST['post_title'];

  $args = array(
    'post_type' => 'post',
    'posts_per_page' => -1
  );

  $posts_array = get_posts( $args );
  $title_array = wp_list_pluck($posts_array, 'post_title'); ?>

 <ul id="post-title-dropdown">
			<?php
				foreach( $title_array as $title ) { ?>
					<?php 
					if ( stripos( $title, $string ) !== false ) { ?>
					
						<li><?php echo $title; ?></li>
						
					<?php
					} 
				}
			?>
		</ul>
	
	<?php
	die();
}

 

Here, we define a function and hook it ‘wp_ajax_(action)’ action hook. WordPress provides us two action hooks – ‘wp_ajax_(action)’ and ‘wp_ajax_nopriv_(action)’ to handle all the AJAX requests. In these hooks, the (action) is replaced by the action that we had previously defined in our data object in the jQuery.post() method. These two hooks perform basically the same function with just a single difference – ‘wp_ajax_nopriv_(action)’ also runs for unauthenticated users or the users who are not logged in. Since we will be performing the AJAX request at the back-end, we do not require ‘wp_ajax_nopriv_(action)’.
In the function, we tell the server what to do with the variables that have been retrieved through the AJAX request. The variables that are passed using jQuery.post() method are retrieved using $_POST[]. After that, we use the get_posts() function to call all posts and the wp_list_pluck() function to get the title of all the posts. Now, we have an array of titles of all the posts. We loop through this array to sort out only those titles which match the value of the Input Text Box and create an unordered list of the same.
This output is then passed on to the callback function in our jQuery.post() method and the empty ‘#search-results’ div is filled with the result.

Now, the AJAX functionality is working and titles are loading based on the content of the Input Box. The only thing that remains is the ability to select the title from the dropdown. We are going to add some JS to enable this functionality. The final JS code will be as follows-

 


jQuery( '#post_search' ).on( 'input', function() {
		
		var titleInput	=	jQuery( this ).val();
		
		if ( titleInput	===	'' ) {
			jQuery(this).html('');
			return;
		}

		data = {
			action: 'post_title_list',
			post_title:	titleInput,
		}
		
		jQuery.post(ajaxurl, data, function( response ) {
			if ( response ) {
				jQuery('#search-results').html( response );
			}
		});
	});
	
	jQuery( '#search-results' ).on( 'click', 'li', function() {
		var currentValue	=	jQuery(this).text();
		jQuery( '#post_search' ).val( currentValue ).trigger( 'change' );
		jQuery(this).parents('#search-results').html('');
	});

 

In order to select the desired Title, we attach a click event to the ‘#search-results’ div. The value of the clicked li element is stored in the currentValue variable. This value is then stored in the Input Text Box and the ‘change’ event is triggered to let the customizer know that a change has occured. After the click, the div is emptied and we are ready to start it all over again.

So, here we have created a Custom Control to select a post just by typing its title in the Input Text Box. This method, although having some pitfalls, is very user-friendly. One of the major drawbacks being running a query everytime a key is pressed on keyboard. This can take a toll on the server. It will be improved overtime. Hope you learnt something new while designing this Custom Control.

Leave a Reply

Your email address will not be published. Required fields are marked *