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'] ); 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.
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.
If you have any questions, I will be happy to help you in comments below.
Comments — 64
Hi Misha,
Thanks for Superb work and ready to use.
How echo Select2 posts as a link on single.php?
Hi,
happy to help :)
If I understand you properly, you can use this:
Thanks it works
Hi Misha. On the first screen I see differentpost types – video, quote, etc. How can I add them to my WordPress instance? Thank you.
You have to add via the functions.php file. Example below:
You can add more post-formats according to your needs.
NOTE: You will need to create several PHP files(one by each post format) in order to get the post formats work. Not to forget that you will need to use the get_template_part(”) WordPress function.
More Info here:
https://codex.wordpress.org/Function_Reference/get_post_format
Hi Misha,
is it possible to choose a post ( by its category ) of another posttype and display it’s content on the frontend, with your plug-in ?
Hi Valentin,
Yes, it is possible.
Hello Misha,
What changing required, if i need to add posts from other CPT.
Two custom post type are:
Add meta box to CPT ‘Apple’
Add Posts from CPT ‘orange’
Hello Kam,
To add metabox for CPT Apple, you have to change custom post type name in Step 1 on lines 9 and 64.
If you want to show posts in dropdown search from CPT orange, in Step 4 in WP_Query add one more parameter
post_type
.Hi Misha,
I am using this query on single.php and trying to show all post here, where meta box has this post.
How to get those posts where meta box have this post or link?
Hi,
Use these
$args
parameters:Hi Misha,
Sorry to say that it have same problem. This show all the post which added to meta box in different posts.
Not show the specific one relate to open post.
What is in your
$post_id
variable? Check if it is correct.I am using default WordPress variable. $ID
Did you check it? Is it correct and not empty?
Yes i check again and again, its correct and not empty.
This query print out all the post which i add to meta box.
But need to print related to current open post.
Show me the content of
$posts
variable which you use forpost__in
parameter of WP_Query.Complete WP_Query
Ok.. Language barrier.. I see.
Please see… Thanks
Answer please my question.
Hello Misha,
You provide me this $args above.
Where you create and use this variable
$posts
Because of that i don’t have any type of content of $posts variable
Thank you for this excellent information no how-to use select2 ajax with WordPress. I adapted it for use on some huge front-end dropdowns I was using, and it is working superbly. The site users are ecstatic because the site is so much faster with ajax for these long selects. Thanks again!
Hi Brad,
That’s awesome! I’m happy to help! :)
Hi Misha,
Thank you for your tutorial!
I would love to integrate the seat chart like this: https://github.com/mateuszmarkowski/jQuery-Seat-Charts to WooCommerce so that I could sell seats online.
Could you feel free to guide me how to do that?
Thank you
Hi John,
I didn’t have a chance to work with this jQuery plugin before :)
Oh, what a pity… Thank you anyway! :)
Hi Misha,
Grand work. But I have a question: I’m trying to use select2 in the frontend and it does not work. I added nopriv to register the ajax url and I get to run the js but it looks like it is not firing the action “mishagetposts”.
Any ideas?
Thank your!!
Hi Ronnie,
Did you include jQuery? What is in your browser console?
Hi again Misha!;
I’ve made it work including the url in the code:
I do not know why I can not access the ajax url in my script as always if the code is correct:
And de js:
Any ideas?
Thank you for answering so quickly.
Ronnie.
Yes,
ajaxurl
is defined only in admin area, so you made everything correctly when include the full URL.But as an option you can define the variable yourself, good practice is to use
wp_localize_script()
function, example is in this post.You’re absolutely right, I forgot to register the url.
Thanks anyway and thanks for sharing documentation.
Greetings from Barcelona!
R.
You’re welcome!
Greetings from Saint Petersburg 🙃
Hi,
thanks for the great solution! works like a charm!
I wonder if it’s possible to also add the possibility to add new tags and not only choose from existing tags?
Thanks again and best,
Niko
Hi Niko,
No 🙃 but the idea is interesting.
Thanks for the fast reply. Unfortunately I’m not really a dev but i think it should be possible – Similar to this solution: http://jsfiddle.net/XQ8Fw/674/
But of course i understand that’s beyond the friendly support :-)
Anyway; If you may sometime include it, please let me know.
Sorry, I just didn’t understand you.
It is possible if you use AJAX method (example with posts). Good news – you do not need to change anything in your JS code.
First Step:
In
wp_ajax_
callback function you have to add a condition – if search query doesn’t match exactly with any of the given results, add another element to the$return
array. I made it with:And got this:

Second Step:
In
save_post
action hook add code that checks uniqueid and if it matches, it creates new element in database, for posts you can usewp_insert_post()
, for post tagswp_insert_term()
.Hi Misha
Thanks so much for sharing this code with the world.
I followed your instructions however I am not able to get the title of the new post inside the save_post action hook (only the id). How can I make the content of $_GET[‘q’] available to save_post.
Again thanks a lot for sharing.
Hi,
Did you try to replace "uniqueid" with the post title?
Hello Misha, Another nice code.
How can I make the tag dropdown Ajax also? I have more that 5000 tags on a wordpress installation.
Hi, thank you,
All the information is in this article 🙃 making tags dropdown is very similar to posts dropdown.
Adamsın :) Perfect
Hello Misha,
I see you are saving the terms in post meta. but isn’t it proper to set post terms? How can I do that?
Hello,
Why?
Because terms need relationship with taxonomy. But in you example terms are saving as post meta not creating relationship with taxonomy (post_tag). How can I do that?
You need
register_taxonomy_for_object_type()
in this case! 😁Hey Misha!
I spent the entire day trying to convert your ideas to search for users, but I can’t seem to find the issue with my code.
Hey,
Do you mean it doesn’t search for users? Check
search_columns
parameter.Hi Misha
I duplicated your metabox to have two of them (I need to display two different CPT links).
I am now having problems with the second WP_Query as I am not able to reset the first WP_Query (So I am always getting the posts from the first WP_Query). Whats the correct way to handle it with your code?
Hi Simon,
Didn’t you forget about
wp_reset_postdata()
function?Hi Misha !
Thank you for this article :)
We are using select2 on a wordpress site.
It is working fine, but it doesn’t display the data after saving or updating the post.
I guess we should include some code in the admin init hook?
I´m not sure, that is my guess..
I will really appreciate any suggestions/guidelines on how to proceed.
Thanks so much,
Seba.
Just one additional comment I just realized.
When I say that the data is not being displayed, I mean on the admin select metabox.
Hey Seba,
so, on the website everything displays ok, right?
Thanks for the great tutorial.
I used it to add admin option input fields with post selection.
On step 4 instead of doing
you could do simply
It does the encoding, echo and die for you.
Awesome!
Thank you for suggestion.
Hi Misha,
Can you please help create a similar tutorial to add select2 to Contact Form 7 (CF7) on a website which also runs Woocommerce?
I am sure the code would be much simpler.
I am learning to code and have found your articles very useful.
Thanks a lot!
Hi,
I’m not sure, but I will think about it.
Thank you for your consideration
Very helpful. Thanks!
Thank you, I followed your instruction and made a custom meta box for my CPT “Artworks” to select terms from custom taxonomy “Object Types” with select2 UI. However, the meta box does not save selected terms.
After saving either draft or published post, there is nothing in metabox field, no selected terms displayed.
What should I check to fix that?
Yes, I have been able to successfully add select2 UI for custom post type following your tutorial. My previous comment contained mistake which I found myself and corrected.
Although I do not fully understand the section of
/* * Select Posts with AJAX search */
Can you explain how to achieve the same by using your plugin? I bought it, but I got no idea how to get select2 on custom metaboxes working using your plugin.
Thank you.
Hello,
If you purchased my plugin, the best of all is to create a ticket here, because I can check what code you’re using and help you to find mistakes in it or to write some ready code for you.
Hi,
thank you so mich. Awesome tutorial.
But I don´t get the post search field to work for a custom post type. Maybe, you can give an example for it too.
Additional, these fields are really nice, but it would be a lot better to have to more options:
1. Decide, if a field is required or not before post submission
2. Set a “Select Option” first option to the field (actually, first term is pre-selected.
I am learning wordpress and you would really help me with examplles.
Later on, I need to select taxonomies inside other taxonomies (as metabox fields) and more… a long progress, but I love to learn :)
Hi Holger,
In Step 4 you can set a
post_type
parameter in WP_Query.Comments are closed.