How to display non-hierarchical taxonomy as terms with checkboxes?

I’d like to have a non-hierarchical custom taxonomy displayed in the add/edit posts admin screen for a custom post type. Obviously, when the custom taxonomy is non-hierarchical, the meta box that’s displayed is similar to the tags – it’s a text field with the auto-suggest.

However, I’m more interested in having a flat, non-hierarchical taxonomy display as a list of checkbox terms. In essence, I’d like it’s functionality to be the same as categories, with the exception that child terms could not be added.

Read More

Surely this is something that other developers have done, but the normal Google searches haven’t returned much for me. Apparently this was the default behavior when custom taxonomies were originally introduced in v2.8.

Example of non-hierarchical taxonomy with checkboxes

I’m really not looking for a plugin solution, however code examples from plugins would be fine. When developing sites for client’s it is often beneficial to allow them to see the list of pre-established terms for a certain post type. The customer should be allowed to add additional terms, just not additional child terms.

Related posts

Leave a Reply

7 comments

  1. Now in 2020, i’ve found the definitive and simpliest solution:

        register_taxonomy( "my_tax", [ "my_post" ], [
            ...
            "meta_box_cb" => "post_categories_meta_box",
        ] );
    

    You can pass the meta_box_cb to change the metabox function. If you use post_categories_meta_box, the non-hierarchy taxonomy will use the hierarchy editor. There is an minor problem here, you still can select the parent category (but it does not set it as an parent category). You can fix this by simply hiding the select input.

  2. I would do that:

    $add_action('add_meta_boxes_my_posttype', 'my_add_meta_boxes');
    
    function my_add_meta_boxes ($post) {
    
        $taxoms = array('my_taxonomy', 'my_second_taxonomy');
    
        foreach ( get_object_taxonomies( $post ) as $tax_name ) {
            if( !in_array($tax_name, $taxoms) ) continue;
    
            $taxonomy = get_taxonomy($tax_name);
            if ( ! $taxonomy->show_ui )
                continue;
    
            $label = $taxonomy->labels->name;
    
            if ( !is_taxonomy_hierarchical($tax_name) ) {
                add_meta_box($tax_name . 'div', $label, 'post_categories_meta_box', null, 'side', 'core', array( 'taxonomy' => $tax_name ));
                remove_meta_box('tagsdiv-' . $tax_name, null, 'side');
            }
        }
    }
    

    After, up to you to hide the parent select box of the form

  3. use hierarchy and hide the parent selects, like this:

    function hide_taxonomy_parent( $slug ) {
        add_action( 'admin_head', function () use ( $slug ) {
            echo "<style>
                .taxonomy-{$slug} .term-parent-wrap,
                [for='new{$slug}_parent'],
                #new{$slug}_parent {
                    display: none !important;
                    visibility: hidden !important;
                }
            </style>";
        } );
    }
    
    hide_taxonomy_parent( 'brand' );
    
  4. My solution:

    function custom_register_taxonomy_args( $args, $name, $object_type ) {
        global $pagenow;
    
        if ( $name == 'product_cat' && ( $pagenow == 'post-new.php' || $pagenow == 'post.php' ) ) {
            $args['hierarchical'] = true;
        }
    
        return $args;
    }
    add_filter( 'register_taxonomy_args', 'custom_register_taxonomy_args', 10, 6 );