Automatically check parent checkbox if child is selected in WordPress

Parent and child walking on the beach while holding hands.
Can't have a child without a parent.

To keep all posts in WordPress organized in terms of categorization, it helps to make sure that when a user selects a category that’s three levels down, i.e. has two parents, that all the corresponding parents get checked.

What follows is a short and sweet JavaScript solution to help the user do this.

Here is how it works:

  1. Find all the checkboxes within in the #categorychecklist container
  2. Bind a change event to each of the checkboxes
  3. If a checkbox is checked, find all the parents and check their immediate child
  4. If a checkbox is unchecked, find all the children and uncheck them
jQuery(document).ready(function($){
  synchronize_child_and_parent_category($);
});

function synchronize_child_and_parent_category($) {
  $('#categorychecklist').find('input').each(function(index, input) {
    $(input).bind('change', function() {
      var checkbox = $(this);
      var is_checked = $(checkbox).is(':checked');
      if(is_checked) {
        $(checkbox).parents('li').children('label').children('input').attr('checked', 'checked');
      } else {
        $(checkbox).parentsUntil('ul').find('input').removeAttr('checked');
      }
    });
  });
}

I have a generic admin.js file in WordPress where I keep little back-end snippets like this.

I then register the script:

wp_register_script(
  PS . '-admin',
  plugins_url('_scripts/admin.js', dirname(dirname(__FILE__))),
  array('jquery')
);

And enqueue it where needed:

wp_enqueue_style(
  PS . '-admin'
);

If you’re curious, the PS (plugin slug) is a constant I define and use infront of many things where I can’t use a PHP namespace, like script and field names, to prevent them from potentially interfering with other plugins.

Lastly, if you’re thinking about using the code above, keep in mind that you’ll also have to prevent checked checkboxes from bubbling to the top, because when a user edits a post with previously checked checkboxes, there’s a good chance the hierarchy will be broken.

Featured image by Derek Thomson.


Comments (5)

Previously posted in WordPress and transferred to Ghost.

Rob
July 12, 2013 at 2:32 pm

Hello.
Thanks for tackling this issue. I tried to follow your steps, but found a simpler solution before I could re-create the php namespace and enqueue it.
http://wordpress.org/plugins/parent-category-toggler/
This does not provide the uncheck options yours does, but it provides the functionality we need.

cheers

Ryan Sechrest
July 12, 2013 at 2:41 pm

Thanks for sharing the alternative solution. In terms of namespace, you don’t have to use namespaces or constants, so you could replace PS . '-admin' with something static like 'my-admin', then this would work for you, too.

Greg Montaño
March 23, 2016 at 9:04 am

Thanks Ryan for this awesome solution and the wp_terms_checklist_args checked_ontop filter! I’ve used it on 2 sites now. Is there a way to prevent checking the parent category if there are sub terms of that term? If the term does not have sub terms, allow checking it. Any help is greatly appreciated!

Ryan Sechrest
March 24, 2016 at 5:29 pm

Hi Greg! You could probably loop through each checkbox, and if it has children, disable the parent by setting the HTML attribute to disabled on it.

Patrick
January 11, 2018 at 1:47 am

Thank you so much for snippet! Exactly what I was looking for and works like charm.

(I only changed #categorychecklist to .cat-checklist since in the quick-edit form there is no id attached to the list – plus I have multiple taxonomies and now it works on all of them in both the quick editor and in the main editor)