I have a list of categories in woo-commerce which I’m trying to customize to be displayed to look like the following image.

List of categories

I created the above image using normal HTML and css however I would like to now convert it to WordPress in order to have it dynamically created.

Here is the HTML:

<div class="col tertiary" id="filters">
        <ul class="product-categories">        

            <li id="pattern_garment_type">
                <h5>Women</h5>
                <ul>
                    <li class="selected">                
                          <a href="#">All</a>                        
                    </li>

                    <li class="">
                      <a href="#">Accessories</a>
                    </li>

                    <li class="">
                      <a href="#">Blouses</a>
                    </li>

                    .etc...

          </ul>
            </li>

            <li id="pattern_garment_type">
                <h5>Men</h5>
                <ul>
                <li class="selected">

                      <a href="#">All</a>

                </li>

                  <li class="">
                      <a href="#">Accessories</a>
                  </li>

                  <li class="">
                      <a href="#">Coats</a>
                  </li>
                  ..etc..

                </ul>
            </li>


            <li id="pattern_garment_type">
                <h5>Kids</h5>
                <ul>
                <li class="selected">

                      <a href="#">All</a>

                </li>

                  <li class="">
                      <a href="#">Babies</a>
                  </li>

                  <li class="">
                      <a href="#">Girls</a>
                  </li>

                  <li class="">
                      <a href="#">Boys</a>
                  </li>

                </ul>
            </li>

        </ul>
    </div>

Here is the current WordPress code I’m working with (not sure if I should use the walker to customize the output to be generated like the HTML above):

  <div id="content-filters" class="two columns">
<?php $args = array(
    'style'              => 'list',
    'show_count'         => 0,
    'use_desc_for_title' => 1,
    'child_of'           => 0,
    'title_li'           => __( '' ),
    'show_option_none'   => __('No Menu Items'),
    'number'             => null,
    'echo'               => 1,
    'depth'              => 2,
    'taxonomy'           => 'product_cat',
); ?>

<div class="col tertiary" id="filters">
    <ul class="product-categories">   
        <?php wp_list_categories( $args ); ?>
    </ul>
</div>

1) How can I use wp_list_categories filter to add an “All” link at the top of the sub categories which links to a page which displays all items.

2) How can I also use the wp_list_categories filter to remove the link from the parent parent category and wrap it in an to make it bold (like in the example image)?

Any help would be appreciated

2 Answers
2

Even if a wp_list_categories filter exists, it passes (and so you have to return) the html markup generated by wp_list_categories() function. This means that if you want use that filter you have to alter the DOM with php, and even if it’s possible (hopefully using external php libraries), sure it’s not the best solution for your needs.
Alternartive are use js to alter html after it was created. It’s a possibility, but I’m a WP developer not a js one, so I’ll give you the Worpress solution.

You have to create a custom Category Walker class and then use it inside a customuized version of wp_list_categories();

Let’s start.

First of all the custom Category Walker class (put it in functions.php):

class My_Category_Walker extends Walker_Category {

  var $lev = -1;
  var $skip = 0;
  static $current_parent;

  function start_lvl( &$output, $depth = 0, $args = array() ) {
    $this->lev = 0;
    $output .= "<ul>" . PHP_EOL;
  }

  function end_lvl( &$output, $depth = 0, $args = array() ) {
    $output .= "</ul>" . PHP_EOL;
    $this->lev = -1;
  }

  function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
    extract($args);
    $cat_name = esc_attr( $category->name );
    $class_current = $current_class ? $current_class . ' ' : 'current ';
    if ( ! empty($current_category) ) {
      $_current_category = get_term( $current_category, $category->taxonomy );
      if ( $category->term_id == $current_category ) $class = $class_current;
      elseif ( $category->term_id == $_current_category->parent ) $class = rtrim($class_current) . '-parent ';
    } else {
      $class="";
    }
    if ( ! $category->parent ) {
      if ( ! get_term_children( $category->term_id, $category->taxonomy ) ) {
          $this->skip = 1;
      } else {
        if ($class == $class_current) self::$current_parent = $category->term_id;
        $output .= "<li class="" . $class . $level_class . "">" . PHP_EOL;
        $output .= sprintf($parent_title_format, $cat_name) . PHP_EOL;
      }
    } else { 
      if ( $this->lev == 0 && $category->parent) {
        $link = get_term_link(intval($category->parent) , $category->taxonomy);
        $stored_parent = intval(self::$current_parent);
        $now_parent = intval($category->parent);
        $all_class = ($stored_parent > 0 && ( $stored_parent === $now_parent) ) ? $class_current . ' all' : 'all';
        $output .= "<li class="" . $all_class . ""><a href="" . $link . "">" . __('All') . "</a></li>\n";
        self::$current_parent = null;
      }
      $link = '<a href="' . esc_url( get_term_link($category) ) . '" >' . $cat_name . '</a>';
      $output .= "<li";
      $class .= $category->taxonomy . '-item ' . $category->taxonomy . '-item-' . $category->term_id;
      $output .=  ' class="' . $class . '"';
      $output .= ">" . $link;
    }
  }

  function end_el( &$output, $page, $depth = 0, $args = array() ) {
    $this->lev++;
    if ( $this->skip == 1 ) {
      $this->skip = 0;
      return;
    }
    $output .= "</li>" . PHP_EOL;
  }

}

It extends the WP Walker_Category and overwrite all the 4 methods with something that fits your needs.

After that, in the functions.php put the customized function:

function custom_list_categories( $args="" ) {
  $defaults = array(
    'taxonomy' => 'category',
    'show_option_none' => '',
    'echo' => 1,
    'depth' => 2,
    'wrap_class' => '',
    'level_class' => '',
    'parent_title_format' => '%s',
    'current_class' => 'current'
  );
  $r = wp_parse_args( $args, $defaults );
  if ( ! isset( $r['wrap_class'] ) ) $r['wrap_class'] = ( 'category' == $r['taxonomy'] ) ? 'categories' : $r['taxonomy'];
  extract( $r );
  if ( ! taxonomy_exists($taxonomy) ) return false;
  $categories = get_categories( $r );
  $output = "<ul class="" . esc_attr( $wrap_class ) . "">" . PHP_EOL;
  if ( empty( $categories ) ) {
    if ( ! empty( $show_option_none ) ) $output .= "<li>" . $show_option_none . "</li>" . PHP_EOL;
  } else {
    if ( is_category() || is_tax() || is_tag() ) {
      $current_term_object = get_queried_object();
      if ( $r['taxonomy'] == $current_term_object->taxonomy ) $r['current_category'] = get_queried_object_id();
    }
    $depth = $r['depth'];
    $walker = new My_Category_Walker;
    $output .= $walker->walk($categories, $depth, $r);
  }
  $output .= "</ul>" . PHP_EOL;
  if ( $echo ) echo $output; else return $output;
}

The hard part is done. Now the template code, put it everywhere you need:

<div id="content-filters" class="two columns">
<div class="col tertiary" id="filters">
<?php
$args = array(
  'taxonomy' => 'product_cat',
  'show_option_none' => __('No Menu Items.'),
  'echo' => 1,
  'depth' => 2,
  'wrap_class' => 'product-categories',
  'level_class' => 'pattern_garment_type',
  'parent_title_format' => '<h5>%s</h5>',
  'current_class' => 'selected'
);
custom_list_categories( $args );
?>
</div>
</div>

Customize the $args if you want, I setted them according to you answer code. Only I have changed ‘pattern_garment_type’ to be class and not an id, because you can’t have the same tag id multiple times in html (as in your markup).

That’s all, hope it helps.

Leave a Reply

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