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

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'] );
			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'] );
			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', '' );
	wp_enqueue_script('select2', '', 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).

	// simple multiple select

	// multiple select with AJAX search
  		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 )
	echo json_encode( $return );

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.

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X