10

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?

11

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.

  • Thank you! Filled in a ton of the 'hows' on this question! – circlesix Jul 2 '16 at 14:31
  • @Khoa TruongDinh thanks for the great answer. This works perfect. Can you please tell me how we can do this same in in the checkout summary section. I have found a lot but cant get a location where to add the new attribute instead of name in checkout summary . – Rohit Goel Mar 6 '17 at 7:04
  • 1
    Be careful, if you have configurable products, you need to override this class also : Magento\ConfigurableProduct\CustomerData\ConfigurableItem and for grouped product : Magento\GroupedProduct\CustomerData\GroupedItem – Franck Garnier Apr 5 '17 at 11:36
  • @FranckGarnier I have just checked seem that we don't need to override these classes. Only add !-- ko text: product_sku --><!-- /ko -->, the sku will show for configurable product. My Magento version is 2.1.5. – Khoa TruongDinh Apr 11 '17 at 1:53
  • 1
    Right for product_sku, but if you need add extra information not natively present, careful about these classes, try to use plugins instead. – Franck Garnier Apr 11 '17 at 13:24
6

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 -->
  • Using 'product_sku' => $this->item->getProduct()->getSku() does work to pull in the sku, so while i don't need the \Magento\Catalog\Model\Product $productModel to grab that, i will use it to grab some other product info. I finally got the preference up and running, so your method does work like a charm! – circlesix Aug 5 '16 at 22:39
  • 1
    For custom attributes you need $productModel to load the product with all attributes and then retrieve them with $this->helper. If it's working you can upvote my answer. – Miroslav Petroff Aug 14 '16 at 4:40
  • 1
    I did, and they only let me vote once. If i could mark your answer as correct as well as Khoa's i would. I'll post around and see if we can get more votes for you, as i have yet to see any one answer this problem anywhere else and this one knocks it out the park. – circlesix Aug 14 '16 at 15:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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