How to use Select2 for your Meta Boxes. Creating AJAX-based Posts Dropdown with Search.

A couple days ago I added to my plugin some types of inputs that allow to multiple select posts and categories. But what if you have thousands of posts? The dropdown AJAX search is also supported. And now I want to share with you how to do it.

/60 comments

Maybe you know, that the most of the code in my posts are ready to use, all you need is just follow the instruction and paste the code to the recommended place.

Step 1. Create a Metabox. Simple Way.

Below is the ready to use code for creating a metabox with two select fields. We will use those selects in next steps. The code can be placed to your theme functions.php or into your custom plugin as an option.

At this moment you can skip this tutorial and use my plugin that actually does the same and much more, but it will save a lot of your time :)

add_action( 'admin_menu', 'rudr_metabox_for_select2' );
add_action( 'save_post', 'rudr_save_metaboxdata', 10, 2 );
 
/*
 * Add a metabox
 * I hope you're familiar with add_meta_box() function, so, nothing new for you here
 */
function rudr_metabox_for_select2() {
	add_meta_box( 'rudr_select2', 'My metabox for select2 testing', 'rudr_display_select2_metabox', 'post', 'normal', 'default' );
}
 
/*
 * Display the fields inside it
 */
function rudr_display_select2_metabox( $post_object ) {
 
	// do not forget about WP Nonces for security purposes
 
	// I decided to write all the metabox html into a variable and then echo it at the end
	$html = '';
 
	// always array because we have added [] to our <select> name attribute
	$appended_tags = get_post_meta( $post_object->ID, 'rudr_select2_tags',true );
	$appended_posts = get_post_meta( $post_object->ID, 'rudr_select2_posts',true );
 
	/*
	 * It will be just a multiple select for tags without AJAX search
	 * If no tags found - do not display anything
	 * hide_empty=0 means to show tags not attached to any posts
	 */
	if( $tags = get_terms( 'post_tag', 'hide_empty=0' ) ) {
		$html .= '<p><label for="rudr_select2_tags">Tags:</label><br /><select id="rudr_select2_tags" name="rudr_select2_tags[]" multiple="multiple" style="width:99%;max-width:25em;">';
		foreach( $tags as $tag ) {
			$selected = ( is_array( $appended_tags ) && in_array( $tag->term_id, $appended_tags ) ) ? ' selected="selected"' : '';
			$html .= '<option value="' . $tag->term_id . '"' . $selected . '>' . $tag->name . '</option>';
		}
		$html .= '<select></p>';
	}
 
	/*
	 * Select Posts with AJAX search
	 */
	$html .= '<p><label for="rudr_select2_posts">Posts:</label><br /><select id="rudr_select2_posts" name="rudr_select2_posts[]" multiple="multiple" style="width:99%;max-width:25em;">';
 
	if( $appended_posts ) {
		foreach( $appended_posts as $post_id ) {
			$title = get_the_title( $post_id );
			// if the post title is too long, truncate it and add "..." at the end
			$title = ( mb_strlen( $title ) > 50 ) ? mb_substr( $title, 0, 49 ) . '...' : $title;
			$html .=  '<option value="' . $post_id . '" selected="selected">' . $title . '</option>';
		}
	}
	$html .= '</select></p>';
 
	echo $html;
}
 
 
function rudr_save_metaboxdata( $post_id, $post ) {
 
	if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;
 
	// if post type is different from our selected one, do nothing
	if ( $post->post_type == 'post' ) {
		if( isset( $_POST['rudr_select2_tags'] ) )
			update_post_meta( $post_id, 'rudr_select2_tags', $_POST['rudr_select2_tags'] );
		else
			delete_post_meta( $post_id, 'rudr_select2_tags' );
 
		if( isset( $_POST['rudr_select2_posts'] ) )
			update_post_meta( $post_id, 'rudr_select2_posts', $_POST['rudr_select2_posts'] );
		else
			delete_post_meta( $post_id, 'rudr_select2_posts' );
	}
	return $post_id;
}

As the result you should got this simple working metabox.

We created a simple metabox with two select multiple elements.
Two selects – the first one will be used just as a multiple selection, to the second one we will add the AJAX post search.

Step 2. Select2 Scripts and Styles – what files to choose?

If everything is clear with Select2 CSS, the javascript library has the standard and the full version. What to use? For the multiple selection and the AJAX feature the standard version is more than enough.

Let’s connect it now using WordPress admin_enqueue_scripts action hook. For your functions.php:

add_action( 'admin_enqueue_scripts', 'rudr_select2_enqueue' );
function rudr_select2_enqueue(){
 
	wp_enqueue_style('select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css' );
	wp_enqueue_script('select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js', array('jquery') );
 
	// please create also an empty JS file in your theme directory and include it too
	wp_enqueue_script('mycustom', get_stylesheet_directory_uri() . '/mycustom.js', array( 'jquery', 'select2' ) ); 
 
}

By the way – I didn’t use the default CSS and copied the styles from WooCommerce (yes, Woo also uses select2 library).

Step 3. Select2 Initialization

Below is the code for mycustom.js (an empty JavaScript file you created in your theme directory in the previous step).

jQuery(function($){
	// simple multiple select
	$('#rudr_select2_tags').select2();
 
	// multiple select with AJAX search
	$('#rudr_select2_posts').select2({
  		ajax: {
    			url: ajaxurl, // AJAX URL is predefined in WordPress admin
    			dataType: 'json',
    			delay: 250, // delay in ms while typing when to perform a AJAX search
    			data: function (params) {
      				return {
        				q: params.term, // search query
        				action: 'mishagetposts' // AJAX action for admin-ajax.php
      				};
    			},
    			processResults: function( data ) {
				var options = [];
				if ( data ) {
 
					// data is the array of arrays, and each of them contains ID and the Label of the option
					$.each( data, function( index, text ) { // do not forget that "index" is just auto incremented value
						options.push( { id: text[0], text: text[1]  } );
					});
 
				}
				return {
					results: options
				};
			},
			cache: true
		},
		minimumInputLength: 3 // the minimum of symbols to input before perform a search
	});
});

Step 4. Search WordPress posts in PHP

Nothing new or especial for you here as well – just a WP_Query loop and WordPress AJAX. Do not know where to insert this code? To functions.php then.

add_action( 'wp_ajax_mishagetposts', 'rudr_get_posts_ajax_callback' ); // wp_ajax_{action}
function rudr_get_posts_ajax_callback(){
 
	// we will pass post IDs and titles to this array
	$return = array();
 
	// you can use WP_Query, query_posts() or get_posts() here - it doesn't matter
	$search_results = new WP_Query( array( 
		's'=> $_GET['q'], // the search query
		'post_status' => 'publish', // if you don't want drafts to be returned
		'ignore_sticky_posts' => 1,
		'posts_per_page' => 50 // how much to show at once
	) );
	if( $search_results->have_posts() ) :
		while( $search_results->have_posts() ) : $search_results->the_post();	
			// shorten the title a little
			$title = ( mb_strlen( $search_results->post->post_title ) > 50 ) ? mb_substr( $search_results->post->post_title, 0, 49 ) . '...' : $search_results->post->post_title;
			$return[] = array( $search_results->post->ID, $title ); // array( Post ID, Post Title )
		endwhile;
	endif;
	echo json_encode( $return );
	die;
}

Finally, the result.

Multiple tags and posts selection and the AJAX search for WordPress posts.
Multiple tags and posts selection and the ability to perform the AJAX search for WordPress posts.

If you have any questions, I will be happy to help you in comments below.

Related Posts

Misha Rudrastyh

Misha Rudrastyh

I love WordPress, WooCommerce and Gutenberg so much. 10 yrs of experience.

Need some custom developer help? Let me know

Follow Misha

Need some help with WordPress?

If you need some professional developer help, I will be happy to assist you.

Contact me Who I am?

Comments — 60

Leave a comment

php js HTML CSS Code