Question

I want to be able to display the product SKU in the mini-cart of a Magento 2 site. But I'm not sure how to use KnockoutJS to pull in additional product information. The template that is being called is here:

vendor/magento/module-checkout/view/frontend/web/template/minicart/item/default.html

And contains code like:

<strong class="product-item-name">
    <!-- ko if: product_has_url -->
    <a data-bind="attr: {href: product_url}, text: product_name"></a>
    <!-- /ko -->
    <!-- ko ifnot: product_has_url -->
        <!-- ko text: product_name --><!-- /ko -->
    <!-- /ko -->
</strong>

So my direct question would be: where are the values for the product set and how can I change them around to add or remove product details?

Was it helpful?

Solution

As far as I know, the header minicart will get the data from customer data

vendor/magento/module-checkout/view/frontend/web/js/view/minicart.js

define([
    'uiComponent',
    'Magento_Customer/js/customer-data',
    'jquery',
    'ko',
    'sidebar'
], function (Component, customerData, $, ko) {
    'use strict';
    ......
    this.cart = customerData.get('cart');
    ......
}

Look into the customer data js vendor/magento/module-customer/view/frontend/web/js/customer-data.js, we can get the customer data from local storage. For example, in your browser console, run the line: localStorage.getItem('mage-cache-storage'), we also can get the cart information. enter image description here

{
  "cart": {
    "summary_count": 1,
    ....
    "items": [
      {
      ......   
        "qty": 1,
        "item_id": "11728",
        "configure_url": "http://magento2-demo/checkout/cart/configure/id/11728/product_id/1817/",
        "is_visible_in_site_visibility": true,
        "product_name": "Breathe-Easy Tank",
        "product_url": "http://magento2-demo/breathe-easy-tank.html",
        "product_has_url": true,
        "canApplyMsrp": false
      }
    ],
    .......
  }
}

Navigate to vendor/magento/module-checkout/CustomerData/DefaultItem.php

protected function doGetItemData()
    {
       .......
        return [
            'options' => $this->getOptionList(),
            'qty' => $this->item->getQty() * 1,
            'item_id' => $this->item->getId(),
            'configure_url' => $this->getConfigureUrl(),
            'is_visible_in_site_visibility' => $this->item->getProduct()->isVisibleInSiteVisibility(),
            'product_name' => $this->item->getProduct()->getName(),
            'product_url' => $this->getProductUrl(),
            'product_has_url' => $this->hasProductUrl(),
           .....
    }

vendor/magento/module-checkout/CustomerData/AbstractItem.php

/**
 * {@inheritdoc}
 */
public function getItemData(Item $item)
{
    $this->item = $item;
    return \array_merge(
        ['product_type' => $item->getProductType()],
        $this->doGetItemData()
    );
}

To get the SKU item, I think we need to add data to getItemData() (Should try with Plugin). And then override the template html vendor/magento/module-checkout/view/frontend/web/template/minicart/item/default.html

 <div class="product-item-details">

                    <!-- ko text: product_sku --><!-- /ko -->

Update Magento 2.1.0 version

In the Magento 2.1.0, you only need to override default.html. This is because the method doGetItemData has already the product sku.

OTHER TIPS

Firstly, very good explanation from @Khoa TruongDinh about the flow of getting item in minicart template.

how can I change them around to add or remove product details?

I found a way how you can extend minicart template with custom attributes of the product. To do that first you need to override vendor/magento/module-checkout/CustomerData/DefaultItem.php with DI Preferences

Create app/code/Vendor/Module/etc/di.xml ot override DefaultItem object

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Checkout\CustomerData\DefaultItem" type="Vendor\Module\Preferences\MiniCartItem" />
</config>

Then create new object to override doGetItemData() method and add custom_attribute with key product_custom_attribute

File: app/code/Vendor/Module/Preferences/MiniCartItem.php

namespace Vendor\Module\Preferences;

class MiniCartItem extends \Magento\Checkout\CustomerData\DefaultItem
{

    public function __construct(
        \Magento\Catalog\Helper\Image $imageHelper,
        \Magento\Msrp\Helper\Data $msrpHelper,
        \Magento\Framework\UrlInterface $urlBuilder,
        \Magento\Catalog\Helper\Product\ConfigurationPool $configurationPool,
        \Magento\Checkout\Helper\Data $checkoutHelper,
        \Magento\Catalog\Helper\Output $helper,
        \Magento\Catalog\Model\Product $productModel
    ) {
        $this->configurationPool = $configurationPool;
        $this->imageHelper = $imageHelper;
        $this->msrpHelper = $msrpHelper;
        $this->urlBuilder = $urlBuilder;
        $this->checkoutHelper = $checkoutHelper;
        $this->helper = $helper;
        $this->productModel = $productModel;
    }

    /**
     * {@inheritdoc}
     */
    protected function doGetItemData()
    {
        $imageHelper = $this->imageHelper->init($this->getProductForThumbnail(), 'mini_cart_product_thumbnail');
        $product = $this->productModel->load($this->item->getProduct()->getId());
        return [
            'options' => $this->getOptionList(),
            'qty' => $this->item->getQty() * 1,
            'item_id' => $this->item->getId(),
            'configure_url' => $this->getConfigureUrl(),
            'is_visible_in_site_visibility' => $this->item->getProduct()->isVisibleInSiteVisibility(),
            'product_name' => $this->item->getProduct()->getName(),
            'product_url' => $this->getProductUrl(),
            'product_has_url' => $this->hasProductUrl(),
            'product_price' => $this->checkoutHelper->formatPrice($this->item->getCalculationPrice()),
            'product_image' => [
                'src' => $imageHelper->getUrl(),
                'alt' => $imageHelper->getLabel(),
                'width' => $imageHelper->getWidth(),
                'height' => $imageHelper->getHeight(),
            ],
            'product_custom_attribute' => $this->helper->productAttribute($product, $product->getCustomAttribute(), 'custom_attribute'),
            'canApplyMsrp' => $this->msrpHelper->isShowBeforeOrderConfirm($this->item->getProduct())
                && $this->msrpHelper->isMinimalPriceLessMsrp($this->item->getProduct()),
        ];
    }
}

Notice that I am injecting

\Magento\Catalog\Model\Product $productModel

to the construct method because I need to load full product data to access my custom_attribute. If there is a better way please tell me.

And finally you can display the new attribute in

view/frontend/web/template/minicart/item/default.html:

 <div class="product-item-details">

                    <!-- ko text: product_custom_attribute --><!-- /ko -->
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top