How to add a custom button to minicart in Magento 2
To create a custom button inside minicart we need to first take a look inside vendor/module-checkout/view/frontend/web/template/minicart/content.html template file:
<!-- /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> <div class="block-title"> <strong> <span class="text" translate="'My Cart'"></span> <span class="qty empty" text="getCartParam('summary_count')" data-bind="css: { empty: !!getCartParam('summary_count') == false }, attr: { title: $t('Items in Cart') }"> </span> </strong> </div> <div class="block-content"> <button type="button" id="btn-minicart-close" class="action close" data-action="close" data-bind=" attr: { title: $t('Close') }, click: closeMinicart() "> <span translate="'Close'"></span> </button> <if args="getCartParam('summary_count')"> <div class="items-total"> <span class="count" if="maxItemsToDisplay < getCartLineItemsCount()" text="maxItemsToDisplay"></span> <translate args="'of'" if="maxItemsToDisplay < getCartLineItemsCount()"></translate> <span class="count" text="getCartParam('summary_count')"></span> <!-- ko if: (getCartParam('summary_count') > 1) --> <span translate="'Items in Cart'"></span> <!--/ko--> <!-- ko if: (getCartParam('summary_count') === 1) --> <span translate="'Item in Cart'"></span> <!--/ko--> </div> <each args="getRegion('subtotalContainer')" render=""></each> <each args="getRegion('extraInfo')" render=""></each> <div class="actions" if="getCartParam('possible_onepage_checkout')"> <div class="primary"> <button id="top-cart-btn-checkout" type="button" class="action primary checkout" data-action="close" data-bind=" attr: { title: $t('Proceed to Checkout') }, click: closeMinicart() " translate="'Proceed to Checkout'"> </button> <div data-bind="html: getCartParamUnsanitizedHtml('extra_actions')"></div> </div> </div> </if> <if args="getCartParam('summary_count')"> <strong class="subtitle" translate="'Recently added item(s)'"></strong> <div data-action="scroll" class="minicart-items-wrapper"> <ol id="mini-cart" class="minicart-items" data-bind="foreach: { data: getCartItems(), as: 'item' }"> <each args="$parent.getRegion($parent.getItemRenderer(item.product_type))" render="{name: getTemplate(), data: item, afterRender: function() {$parents[1].initSidebar()}}"></each> </ol> </div> </if> <ifnot args="getCartParam('summary_count')"> <strong class="subtitle empty" translate="'You have no items in your shopping cart.'"></strong> <if args="getCartParam('cart_empty_message')"> <p class="minicart empty text" text="getCartParam('cart_empty_message')"></p> <div class="actions"> <div class="secondary"> <a class="action viewcart" data-bind="attr: {href: shoppingCartUrl}"> <span translate="'View and Edit Cart'"></span> </a> </div> </div> </if> </ifnot> <div class="actions" if="getCartParam('summary_count')"> <div class="secondary"> <a class="action viewcart" data-bind="attr: {href: shoppingCartUrl}"> <span translate="'View and Edit Cart'"></span> </a> </div> </div> <div id="minicart-widgets" class="minicart-widgets" if="regionHasElements('promotion')"> <each args="getRegion('promotion')" render=""></each> </div> </div> <each args="getRegion('sign-in-popup')" render=""></each>
So according to the template file there can be 2 approaches:
- Create a custom template file for extra-info renderer and then pass a custom component.
- Override content.html template file and push html changes inside
1. Pass custom component to template:
Create default.xml file:
Know/Module/view/frontend/layout/default.xml
<?xml version="1.0" encoding="UTF-8" ?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="minicart"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="minicart_content" xsi:type="array"> <item name="children" xsi:type="array"> <item name="extra_info" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Know_Module/extra-info</item> </item> <item name="children" xsi:type="array"> <item name="extra_info_btn" xsi:type="array"> <item name="component" xsi:type="string">Know_Module/js/custom-button</item> <item name="displayArea" xsi:type="string">extraInfoBtn</item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page>
Now create extra-info template file:
Know/Module/view/frontend/web/template/extra-info.html
<each args="getRegion('extraInfoBtn')" render=""></each>
Then create custom-button component file:
Know/Module/view/frontend/web/js/custom-button.js
define([ 'uiComponent', 'ko' ], function (Component, ko) { 'use strict'; return Component.extend({ defaults: { template: 'Know_Module/custom-button' }, btnContent: ko.observable(''), initialize: function () { this._super(); this.fetchButtonContent(); }, fetchButtonContent: function () { let button = document.createElement('button'); button.className = 'action'; button.classList.add('primary'); button.textContent = 'External button'; this.btnContent(button.outerHTML); } }); });
Next create the component template file:
Know/Module/view/frontend/web/template/custom-button.html
<div data-bind="html: btnContent()"></div>
Flush the cache and clear the static or generated content:
php bin/magento c:c rm -r generated/* var/cache/* var/view_preprocessed/* pub/static/*
The output to the above will look like the screenshot below:
2. Override content.html template file:
Modify the default.xml layout file and make following changes:
Know/Module/view/frontend/layout/default.xml
<?xml version="1.0" encoding="UTF-8" ?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="minicart"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="minicart_content" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">Know_Module/minicart/content</item> </item> <item name="children" xsi:type="array"> <item name="extra_info_btn" xsi:type="array"> <item name="component" xsi:type="string">Know_Module/js/custom-button</item> <item name="displayArea" xsi:type="string">extraInfoBtn</item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page>
Now create content.html template file:
Know/Module/view/frontend/web/template/minicart/content.html
<!-- /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> <div class="block-title"> <strong> <span class="text" translate="'My Cart'"></span> <span class="qty empty" text="getCartParam('summary_count')" data-bind="css: { empty: !!getCartParam('summary_count') == false }, attr: { title: $t('Items in Cart') }"> </span> </strong> </div> <div class="block-content"> <button type="button" id="btn-minicart-close" class="action close" data-action="close" data-bind=" attr: { title: $t('Close') }, click: closeMinicart() "> <span translate="'Close'"></span> </button> <if args="getCartParam('summary_count')"> <div class="items-total"> <span class="count" if="maxItemsToDisplay < getCartLineItemsCount()" text="maxItemsToDisplay"></span> <translate args="'of'" if="maxItemsToDisplay < getCartLineItemsCount()"></translate> <span class="count" text="getCartParam('summary_count')"></span> <!-- ko if: (getCartParam('summary_count') > 1) --> <span translate="'Items in Cart'"></span> <!--/ko--> <!-- ko if: (getCartParam('summary_count') === 1) --> <span translate="'Item in Cart'"></span> <!--/ko--> </div> <each args="getRegion('subtotalContainer')" render=""></each> <each args="getRegion('extraInfo')" render=""></each> <div class="actions" if="getCartParam('possible_onepage_checkout')"> <div class="primary"> <button id="top-cart-btn-checkout" type="button" class="action primary checkout" data-action="close" data-bind=" attr: { title: $t('Proceed to Checkout') }, click: closeMinicart() " translate="'Proceed to Checkout'"> </button> <div data-bind="html: getCartParamUnsanitizedHtml('extra_actions')"></div> </div> </div> </if> <if args="getCartParam('summary_count')"> <strong class="subtitle" translate="'Recently added item(s)'"></strong> <div data-action="scroll" class="minicart-items-wrapper"> <ol id="mini-cart" class="minicart-items" data-bind="foreach: { data: getCartItems(), as: 'item' }"> <each args="$parent.getRegion($parent.getItemRenderer(item.product_type))" render="{name: getTemplate(), data: item, afterRender: function() {$parents[1].initSidebar()}}"></each> </ol> </div> </if> <ifnot args="getCartParam('summary_count')"> <strong class="subtitle empty" translate="'You have no items in your shopping cart.'"></strong> <if args="getCartParam('cart_empty_message')"> <p class="minicart empty text" text="getCartParam('cart_empty_message')"></p> <div class="actions"> <div class="secondary"> <a class="action viewcart" data-bind="attr: {href: shoppingCartUrl}"> <span translate="'View and Edit Cart'"></span> </a> </div> </div> </if> </ifnot> <div class="actions" if="getCartParam('summary_count')"> <div class="secondary"> <a class="action viewcart" data-bind="attr: {href: shoppingCartUrl}"> <span translate="'View and Edit Cart'"></span> </a> </div> </div> <div id="minicart-widgets" class="minicart-widgets" if="regionHasElements('promotion')"> <each args="getRegion('promotion')" render=""></each> </div> <div id="custom-button"> <each args="getRegion('extraInfoBtn')" render=""></each> </div> </div> <each args="getRegion('sign-in-popup')" render=""></each>
Flush the cache and clear the static or generated content:
php bin/magento c:c rm -r generated/* var/cache/* var/view_preprocessed/* pub/static/*
Now the output will look like the screenshot below:
That’s all. Thank you for reading the post.