How to add a custom button to minicart in Magento 2

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:

  1. Create a custom template file for extra-info renderer and then pass a custom component.
  2. 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:

minicart-custom-button-extra-info

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:

minicart-custom-button-override-template

That’s all. Thank you for reading the post.

How useful was this post?

Click on a star to rate it!

Average rating / 5. Vote count:

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Leave a Reply

Your email address will not be published. Required fields are marked *