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: ,

6 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 ­čÖé

Leave a Reply

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