Creating single select WordPress taxonomies

As most of you would have already know, WordPress by default provides two built-in taxonomies – Categories and Tags. If you need to create a new association, then it is also very easy to create custom taxonomies in WordPress.

But one of the major limitations while creating custom taxonomies in WordPress is that you can’t make them as “single select”. By “single select” I mean the ability to restrict only one term to be selected for a post.

Following in one example where you might need this ability. Let’s say you are storing movie information in a custom post type and you need to store the PG rating for the movie in a custom taxonomy. Each movie will have only one rating and you should restrict that only one rating term is stored for a movie.

Recently I faced a similar scenario and this post talks about how I solved it.

Default Taxonomy types in WordPress

WordPress by default supports only two types of taxonomies.

  • Hierarchical taxonomies, which are like categories. You can have multiple hierarchies and they are rendered using checkboxes.
  • Non Hierarchical taxonomies, which are like tags. Here you create specify a list of comma separated taxonomy terms for a post.

As you might have already noted, in both the above two types you can’t restrict a post to have only one term selected from a given taxonomy.

Custom Field vs Custom Taxonomy

One option to solve this issue is to create a custom meta box and store the information in custom field.

This approach allows you to create your own UI, but if you need to retrieve posts based on the value in the field then you have to query your posts based on meta data which is generally slower than retrieving posts based on taxonomies.

Convert taxonomies into single select

The approach that I took to solve this problem is to create a custom meta box to display the taxonomies as radio buttons and then save the terms to the post as taxonomies when the post is saved.

Using a custom meta box to display the taxonomy

We can use a custom meta box for displaying the taxonomy instead of the built-in one by specifying the function that prints the meta box to the meta_box_cb options of the args parameter that is passed to the register_taxonomy function.

And then inside the function we can fetch the term that is associated with the post and then display the radio buttons (or a dropdown).

Saving the term to the taxonomy

Now when a user saves the post, we can hook into the save_post hook and then save the term as part of the taxonomy for that post.

Making sure the term is selected

If the term is mandatory then we can also send a error message back to the user (and change the post to draft) using the edit_form_top hook if the user has not selected at least one term.

This validation can also be done in the frontend using JavaScript.

Source code

The entire source code is available as a gist. The code can be either added to your theme’s functions.php file or as a separate plugin. Make sure you use the correct taxonomy name when you use this code.

Related posts

Tags: ,

16 Comments so far

Follow up comments through RSS Feed | Post a comment

  • Corey says:

    Thank you for writing this post, it really helped me transform the checkboxes into select drop-downs.

  • M Adeel says:

    Thanks for this great tip!

    Adding a little improvement, if you name your input field “tax_input[movie_rating]” (movie_rating being your taxonomy name) and set the value to term name, then you won’t have to implement any hook to save the value. It will be saved automatically. At least it works in WP 4.4.

    • M Adeel says:

      Note!
      In case of a hierarchical taxonomy, the input name should have additional braces (tax_input[movie_rating][]) and its value should be term id instead of term name. And then of course the checked input logic will also have to use the id instead of the name.

  • Ksenia says:

    Thanks a lot for the excellent piece of code! Works like charm! Always wanted to use my custom taxonomies like that 🙂

  • Greg says:

    Thanks a lot!

  • sarah zayat says:

    Thank you for this code , it’s really beneficial, but how can i make it work with ACF ( advanced custom

  • Thoman Phan says:

    Hello
    My website has so many taxonomy, can you help me show only one taxonomy selected on wp admin edit post ?
    current I set hidden taxonomy with show_ui is false

    register_taxonomy(‘developer’, ‘post’, array(
    ‘hierarchical’ => true,
    ‘labels’ => $labels, /* NOTICE: Here is where the $labels variable is used */
    ‘show_ui’ => FALSE,
    ‘query_var’ => true,
    ‘rewrite’ => array(‘slug’ => ‘developer’),
    ));

  • 1452345 says:

    You are saving the “name” of the term as the value of the select, and them searching for it by name on the server side.

    you could just

    value=”term_id ); ?>”
    instead of
    value=”name ); ?>”

    and then you can save the ID directly.

  • Danny says:

    This is great, thanks.

    The only problem I’m having is that the post is publishing even if I don’t select a tax.

    I get the error telling me it needs to be selected, but the post status still sets to published.

    How comes and how do I keep it as Draft if its not selected?

  • Sakshi Sharma says:

    Thankx alot for great tips.

  • Rob says:

    Unfortunately this no longer display the meta box in gutenberg – looking for a solution!

  • AppMySite says:

    Great article.

  • Tom J Nowell says:

    Noting that the code in this article uses esc_attr_e to escape and echo dynamic values, but this is incorrect. esc_attr_e is a localisation function. esc_attr_e and esc_html_e are not shorthand for echo esc_attr, they’re short for echo esc_attr( __( and echo esc_html( __(

    This means that if your value matches a translated string it could be translated into another language by accident.

    Instead the correct thing to do is echo esc_attr( and echo esc_html(

Leave a Reply

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