Magento 2.2.4 – Breadcrumbs Not Showing on Product Pages Without Default Navigation

breadcrumbsmagento2

I have a Megamenu extension installed replacing the default navigation menu. This however when added breaks breadcrumbs on product pages.

I have debugged by also removing both navigation and this also breaks the navigation so I believe the issue lies with default navigation being required somehow for breadcrumbs to work now. I could of sworn however this was working on 2.2.4 earlier this week as had below issue:

Issue with Magento 2.2.4 – quotation mark in product name break product pages

This i resolved however am sure did not break breadcrumbs as the time. Reverting does not fix breadcrumbs either.

How do breadcrumbs work now? They seem to load asynchronously and not sure they did before.

From what i can tell the below function in breadcrumbs.js renders the breadcrumbs:

    _render: function () {
        var html,
            crumbs = breadcrumbList,
            template = mageTemplate(tpl);

        this._decorate(crumbs);

        html = template({
            'breadcrumbs': crumbs
        });

        if (html.length) {
            $(this.element).html(html);
        }
    },

However im not sure how it grabs the data for the html variable and why it breaks when i remove the default navigation.

Best Answer

With help of some posts on stackexchange, I found out this solution, This approach does not require you to override with di.xml

YOUR_THEME\Magento_Catalog\layout\catalog_product_view.xml

<referenceContainer name="content.top">
    <block class="Vendor\Module\Block\Breadcrumbs" name="breadcrumbs" as="breadcrumbs" />
</referenceContainer>

Create a module with the following block:

Vendor/Module/Block/Breadcrumbs.php

<?php

namespace Vendor\Module\Block;

use Magento\Catalog\Helper\Data;
use Magento\Framework\View\Element\Template\Context;
use Magento\Store\Model\Store;
use Magento\Framework\Registry;

class Breadcrumbs extends \Magento\Theme\Block\Html\Breadcrumbs
{
    /**
     * Catalog data
     *
     * @var Data
     */
    protected $_catalogData = null;

    /**
     * @param Context $context
     * @param Data $catalogData
     * @param array $data
     */
    public function __construct(Context $context, Data $catalogData, Registry $registry, array $data = [])
    {
        $this->_catalogData = $catalogData;
        $this->registry = $registry;
        parent::__construct($context, $data);
    }

    /**
     * Retrieve HTML title value separator (with space)
     *
     * @param null|string|bool|int|Store $store
     * @return string
     */
    public function getTitleSeparator($store = null)
    {
        $separator = (string)$this->_scopeConfig->getValue('catalog/seo/title_separator', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store);
        return ' ' . $separator . ' ';
    }
    
    public function getCrumbs() {
        return $this->_crumbs;
    }

    /**
     * Preparing layout
     *
     * @return \Magento\Catalog\Block\Breadcrumbs
     */
    protected function _prepareLayout() {

        $title = [];
        if ($breadcrumbsBlock = $this->getLayout()->getBlock('breadcrumbs')) {
            $breadcrumbsBlock->addCrumb(
                    'home', [
                'label' => __('Home'),
                'title' => __('Go to Home Page'),
                'link' => $this->_storeManager->getStore()->getBaseUrl()
                    ]
            );
            $path = $this->_catalogData->getBreadcrumbPath();
            $product = $this->registry->registry('current_product');

            if ($product && count($path) == 1) {
                $categoryCollection = clone $product->getCategoryCollection();
                $categoryCollection->clear();
                $categoryCollection->addAttributeToSort('level', $categoryCollection::SORT_ORDER_DESC)->addAttributeToFilter('path', array('like' => "1/" . $this->_storeManager->getStore()->getRootCategoryId() . "/%"));
                $categoryCollection->setPageSize(1);
                $breadcrumbCategories = $categoryCollection->getFirstItem()->getParentCategories();

                foreach ($breadcrumbCategories as $category) {
                    $catbreadcrumb = array("label" => $category->getName(), "link" => $category->getUrl());
                    $breadcrumbsBlock->addCrumb("category" . $category->getId(), $catbreadcrumb);
                    $title[] = $category->getName();
                }
                //add current product to breadcrumb
                $prodbreadcrumb = array("label" => $product->getName(), "link" => "");
                $breadcrumbsBlock->addCrumb("product" . $product->getId(), $prodbreadcrumb);
                $title[] = $product->getName();
            } else {
                foreach ($path as $name => $breadcrumb) {
                    $breadcrumbsBlock->addCrumb($name, $breadcrumb);
                    $title[] = $breadcrumb['label'];
                }
            }
            $this->pageConfig->getTitle()->set(join($this->getTitleSeparator(), array_reverse($title)));
            return parent::_prepareLayout();
        }
        $path = $this->_catalogData->getBreadcrumbPath();
        foreach ($path as $name => $breadcrumb) {
            $title[] = $breadcrumb['label'];
        }
        $this->pageConfig->getTitle()->set(join($this->getTitleSeparator(), array_reverse($title)));
        return parent::_prepareLayout();
    }
}

YOUR_THEME\Magento_Catalog\templates\product\breadcrumbs.phtml

<?php if ($crumbs && is_array($crumbs)) : ?>
    <div class="breadcrumbs">
        <ul class="items">
        <?php foreach ($crumbs as $crumbName => $crumbInfo) : ?>

            <?php
                $label = $block->escapeHtml($crumbInfo['label']);
                $link = $block->escapeUrl($crumbInfo['link']);
            ?>

            <li class="item <?php /* @escapeNotVerified */ echo $block->escapeHtml($crumbName) ?>">
            <?php if ($link) : ?>
                    <a href="<?php /* @escapeNotVerified */ echo $link ?>"
                       title="<?= $block->escapeHtml($crumbInfo['title']) ?>">
                    <?= $label ?>
                    </a>
                    <?php elseif ($crumbInfo['last']) : ?>
                    <strong><?= $label ?></strong>
                <?php else: ?>
                    <?= $label ?>
                <?php endif; ?>
            </li>
        <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>