4

I am attempting to create a A-Z category listing within a static block, something like the attached image.

The static block will be on the parent category, and the listing will show the parent categories children.

Can anyone please suggest how I can achieve this in Magento 2?

enter image description here

1 Answer 1

0

I've done something simmilar in the past to sort brands (which are basically categories).

You could inject a custom block into the static block

{{block class="Vendor\Module\Block\AlphabetCategories" template="Vendor_Module::template.phtml"}}

Create the mentioned block class and create a method that fetches the categories needed (please rewrite this so it will work in your case):

public function getBrandsCategory($limit = null, $order = 'position')
{
    $brandsCatId = 123;
    $rootCategory = ($this->_getRootCategoryId()) ?: '2';

    $collection = $this->_categoryCollection
        ->addAttributeToSelect(['name', 'path', 'url_key', 'position', 'level', 'include_in_menu'])
        ->addFieldToFilter('path', ['like' => "1/{$rootCategory}/{$brandsCatId}/%"])
        ->addLevelFilter(3)
        ->addIsActiveFilter()
        ->setPageSize($limit)
        ->setCurPage(1)
        ->addOrderField('level')
        ->addOrderField($order);

    return $collection;
}

You can then sort the collection in the template (you could or should do that in the block class)

$allBrands = $alphabet = [];
foreach ($block->getBrandsCategory(null, 'name') as $item) {
    $letter = substr($item->getName(), 0, 1);
    $allBrands[$letter][$item->getId()] = [
        'name' => $item->getName(),
        'url' => $baseUrl . $item->getRequestPath()
    ];
    $alphabet[$letter] = $letter;
}
ksort($alphabet);
ksort($allBrands);

You can then iterate through the sorted array of categories. Note that this may only work with letters - use your imagination for the numbers/symbols bit :)

<?php foreach ($allBrands as $letter => $cats) : ?>
    <div class="brands-letter" id="brands-<?php echo strtolower($letter) ?>">
        <div class="big-letter"><?php echo $letter ?></div>
        <div class="letter-brands-wrapper<?php echo (count($cats) <= 9) ? ' col-3' : '' ?>">
            <?php foreach ($cats as $cat) : ?>
                <div class="brand-item">
                    <a href="<?php echo $cat['url'] ?>">
                        <span><?php echo $cat['name'] ?></span>
                    </a>
                </div>
            <?php endforeach ?>
        </div>
    </div>
<?php endforeach ?>

For the top navigation you can use the other array (just letters):

<div class="brands-nav">
    <ul>
        <?php foreach ($alphabet as $letter) : ?>
            <li><a href="#brands-<?php echo strtolower($letter) ?>"><?php echo $letter ?></a></li>
        <?php endforeach ?>
    </ul>
</div>
3
  • Thanks Zankar... I've done the above but get the message 'We're sorry, an error has occurred while generating this content. ' I have added the first two blocks of code into the 'AlphabetCategories.php' file is this correct?' Sep 25, 2018 at 15:34
  • 1
    @YorkieMagento this generally means there was an error generating content in a block you added to the page. This could mean a missing template or an error in the PHP code. Only the top block of code goes into the class (AlphabetCategories.php) (public function getBrandsCategory()...) the rest goes into the template. Check if your code returns a collection. Put something like var_dump($block->getBrandsCategory()) in your template and comment out the rest of the code. Also check your logs :)
    – Zankar
    Sep 26, 2018 at 5:59
  • Hi Zankar, the good news is, it's now found the module. The bad news is, it results in a completely empty page Is the 'root category' the parent category (i.e. default in this case)? Sep 26, 2018 at 9:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.