skip to Main Content

I am using a Product Categories List Block to list all product categories in sidebar in shop and category pages (like filters). I am listing categories in my site by using a wordpress Widget. Categories are shown but there is no active class for current category or ancestor category. How to make it that if user is on current category, the li item will get current-cat class and ancestor current-ancestor class?

HTML STRUCTURE OF WIDGET

2

Answers


  1. I needed to solve this myself, so here is my current solution.

    Since there is currently no filter available for the default WooCommerce blocks, I solved it using PHP’s DOMDocument parser while rendering the block.

    You can add a filter to render_block to catch the html for the specific block, in this case the block name is woocommerce/product-categories. By adding checks for non-admin & non-json requests we make sure the changes only happen on the front-end output.

    If you add the code below to your theme’s functions.php, a class current-category-item is added to the list item that matches the current url.

    function custom_render_block_wc_product_categories(string $block_content, array $block): string
    {
        if(
            $block['blockName'] !== 'woocommerce/product-categories'
            || is_admin()
            || wp_is_json_request()
        ) {
            return $block_content;
        }
    
        $html = '';
    
        global $wp;
        $current_slug = trim($wp->request,'/');
    
        $dom = new DOMDocument();
        $dom->loadHTML($block_content);
        $elements = $dom->getElementsByTagName('a');
    
        if( $elements['length'] ){
            foreach ($elements as $node){
                $href = parse_url($node->getAttribute('href'));
                $path = trim($href['path'], '/');
    
                if( $path === $current_slug ){
                    $class = $node->parentNode->getAttribute('class');
                    $class .= ' current-category-item';
                    $node->parentNode->setAttribute('class', $class);
                    break;
                }
            }
        }
    
        $html .= "<div class='block-outer-wrapper'>";
        $html .= "<header><h4>" . __('Categories','woocommerce') . "</h4></header>";
        $html .= $dom->saveHTML();
        $html .= "</div>";
    
        return $html;
    }
    add_filter('render_block', 'custom_render_block_wc_product_categories', 10, 2);
    

    I also added a header to the block, but these lines are optional as long as you return $dom->saveHTML() after your changes.

    Login or Signup to reply.
  2. it works very well, but I edited this line

    > $dom->loadHTML($block_content);
    

    to

    > $dom->loadHTML( '<meta http-equiv="content-type" content="text/html;
    > charset=utf-8">' . $block_content);
    

    my site is in Cyrillic and it breaks the encoding

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search