WordPress.org

Make WordPress Core

Opened 5 years ago

Last modified 10 months ago

#33841 new enhancement

WP_Dropdown_Categories: Parent Category Optgroups

Reported by: tifosi Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.4
Component: Taxonomy Keywords:
Focuses: Cc:

Description

On a number of occasions I've structured a hierarchical taxonomy with parent > child categories, but have only wanted to be able to select the child categories. An example of this is country > county, or manufacturer > model.

The best way to do this is to set the parent category as an optgroup. wp_dropdown_categories() doesn't handle this through the Walker_CategoryDropdown class.

I would like a new option for the wp_dropdown_categories() function arguments to enable this, for example:
parent_optgroup = true (default, false)

This could either trigger a flow change in the walker class, or the use of an extended class. I'm currently using an override to the walker argument to the function - the codex doesn't advertise this is available, but works:

$args = array(
    ....
    'hierarchical'   => 1, 
    'taxonomy'       => $taxonomy,
    'walker'         => new Walker_CategoryDropdown_Optgroup 
); 
wp_dropdown_categories( $args );             
/**
 * Parent level optgroup walker extension
 */
class Walker_CategoryDropdown_Optgroup extends Walker_CategoryDropdown {

    var $optgroup = false;

    function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {

        $pad = str_repeat(' ', $depth * 3);
        $cat_name = apply_filters('list_cats', $category->name, $category);
            
        // set parent optgroup            
        if (0 == $depth) {
            $this->optgroup = true;
            $output .= '<optgroup class="level-$depth" label="' . $cat_name . '" >';           
        } else {
            $this->optgroup = false;
            $output .= '<option class="level-' . $depth. '" value="' . $category->term_id . '"';
            if ( $category->term_id == $args['selected'] ) {
                $output .= ' selected="selected"';
            }
            $output .= '>' . $pad.$cat_name;
            if ( $args['show_count'] ) {
                $output .= '  ('. $category->count .')';
            }
            $output .= "</option>";
        }
    }

    function end_el( &$output, $object, $depth = 0, $args = array() ) {
         
        if ( 0 == $depth && true == $this->optgroup ) {
            $output .= '</optgroup>';
        }
    }
}

This sets the parent term (depth 0) as an optgroup, and all child elements are left as standard select options.

Change History (1)

#1 @Kopepasah
4 years ago

@tifosi at its current state you are turing every single parent into an option group, but something to consider is allowing for the creation of terms at the top level (childless) without having to exist in an option group.

Another thing to consider is the UI for selecting categories in the edit screen. If the parent item is merely an option group, it should not be a checkbox on the edit screen (because it is not a "real" term"). Furthermore, should parent items have an archive view within the theme (thinking out loud)?

Maybe this should exist as a plugin which allows for you to create option groups of specific taxonomy term to display using a custom callback (just spitballing)?

Nevertheless, this would be a great feature (I would use it)... just need to workout precisely how this is implemented and does it belong in Core or as a plugin.

Note: See TracTickets for help on using tickets.