0

I am using magento 2

in mini cart, I am trying to get the event during which product is being added and removed, a specific item not by cart

enter image description here

enter image description here

shown is the item that exists in mini cart, I want that when the user click the "Update" button it is able to retrieve the details of that product being updated in javascript

I am able to get the location of the code here at

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

I am able to know that this is the correct code

<div class="details-qty qty">
        <label class="label" data-bind="i18n: 'Qty', attr: {
                for: 'cart-item-'+item_id+'-qty'}"></label>
        <input data-bind="attr: {
                id: 'cart-item-'+item_id+'-qty',
                'data-cart-item': item_id,
                'data-item-qty': qty,
                'data-cart-item-id': product_sku
                }, value: qty"
                type="number"
                size="4"
                class="item-qty cart-item-qty">
        <button data-bind="attr: {
                id: 'update-cart-item-'+item_id,
                'data-cart-item': item_id,
                title: $t('Update')
                }"
                class="update-cart-item"
                style="display: none">
            <span data-bind="i18n: 'Update'"></span>
        </button>
    </div>
</div>

because when I try to change the 'Update' value to a different value it is reflected into the mini cart

Thus from this view I try to find where the javascript is being triggered , I search for any input that trigger the class 'update-cart-item' and able to find the location of code that call the tempate file that contains 'update-cart-item' is at here

app/design/frontend/MageBig/martfury/project01/Magento_Checkout/web/js/view/summary/item/details.js

content of the code are as below

define([
    'jquery',
    'uiComponent',
    'Magento_Customer/js/model/authentication-popup',
    'Magento_Customer/js/customer-data',
    'Magento_Checkout/js/model/quote',
    'Magento_Checkout/js/action/get-totals',
    'Magento_Checkout/js/model/shipping-service',
    'Magento_Checkout/js/model/shipping-rate-registry',
    'Magento_Checkout/js/model/resource-url-manager',
    'mage/storage',
    'Magento_Checkout/js/model/error-processor',
    'mage/url',
    'Magento_Ui/js/modal/alert',
    'Magento_Ui/js/modal/confirm',
    'underscore',
    'jquery/ui',
    'mage/decorate',
    'mage/collapsible',
    'mage/cookies'
], function ($, Component, authenticationPopup, customerData, quote, getTotalsAction, shippingService, rateRegistry, resourceUrlManager, storage, errorProcessor, url,alert, confirm, _) {
    'use strict';

    return Component.extend({
        shoppingCartUrl: window.checkout.shoppingCartUrl,
        defaults: {
            template: 'Magento_Checkout/summary/item/details'
        },

        /**
         * @param {Object} quoteItem
         * @return {String}
         */
        getValue: function (quoteItem)
        {
            return quoteItem.name;
        },
        updateItemQtyCheckout: function (data, event)
        {
            var btnminus = "";
            var btnplus = "";
            if (event.target.classList[1] == "minus")
            {
                btnminus = event.currentTarget.dataset.btnMinus;
            }
            if (event.target.classList[1] == "plus")
            {
                btnplus = event.currentTarget.dataset.btnPlus;
            }
            var itemId = event.currentTarget.dataset.cartItem;


            // If element is minus and quantity is '1' than remove
            var elem = $('#cart-item-' + itemId + '-qty');
            if(event.target.classList[1] == 'plus'){
                 elem.val(parseInt(elem.val()) + 1)
            }else if(event.target.classList[1] == 'remove'){
                elem.val(0)
            }else if(event.target.classList[1] == 'minus'){
                elem.val(parseInt(elem.val()) - 1)
            }
                

            if ((event.target.classList[1] == "minus" || event.target.classList[1] == "remove") && $('#cart-item-' + itemId + '-qty').val() == '0')
            {   
                var productData = this._getProductById(Number(itemId));

                if (!_.isUndefined(productData))
                {
                    var self = this;
                    var elemr = elem;
                    self._ajax(url.build('checkout/sidebar/removeItem'), {
                                    'item_id': itemId
                                }, elemr, self._removeItemAfter);

                    if (window.location.href === self.shoppingCartUrl)
                    {
                          window.location.reload(false);
                    }
                    
                }
            }
            else
            {
                this._ajax(url.build('checkout/sidebar/updateItemQty'), {
                    'item_id': itemId,
                    'item_qty': $('#cart-item-' + itemId + '-qty').val(),
                    'item_btn_plus': btnplus,
                    'item_btn_minus': btnminus
                }, elem, this._updateItemQtyAfter);
            }
        },
        _getProductById: function (productId)
        {
            return _.find(customerData.get('cart')().items, function (item)
            {
                return productId === Number(item['item_id']);
            });
        },
        _updateItemQtyAfter: function (elem)
        {
            var productData = this._getProductById(Number(elem.data('cart-item')));

            if (!_.isUndefined(productData)) 
            {
                $(document).trigger('ajax:updateCartItemQty');

                if (window.location.href === this.shoppingCartUrl)
                {
                    window.location.reload(false);
                }
            }
            this._hideItemButton(elem);
            this._customerData();
        },
        _customerData: function ()
        {
            var deferred = $.Deferred();
            getTotalsAction([], deferred);
            var sections = ['cart'];
            customerData.invalidate(sections);
            customerData.reload(sections, true);
            var self = this;
            self._estimateTotalsAndUpdateRatesCheckout();
        },
        _ajax: function (url, data, elem, callback)
        {
            $.extend(data, {
                'form_key': $.mage.cookies.get('form_key')
            });

            $.ajax({
                url: url,
                data: data,
                type: 'post',
                dataType: 'json',
                context: this,

                /** @inheritdoc */
                beforeSend: function ()
                {
                    elem.attr('disabled', 'disabled');
                },

                /** @inheritdoc */
                complete: function ()
                {
                    elem.attr('disabled', null);
                }
            })
                .done(function (response)
                {
                    var msg;

                    if (response.success)
                    {
                        callback.call(this, elem, response);
                    }
                    else
                    {
                        msg = response['error_message'];

                        if (msg)
                        {
                            alert({
                                content: msg
                            });
                        }
                    }
                })
                .fail(function (error)
                {
                    console.log(JSON.stringify(error));
                });
        },
        _hideItemButton: function (elem)
        {
            var itemId = elem.data('cart-item');

            $('#update-cart-item-' + itemId).hide('fade', 300);
        },
        _removeItemAfter: function (elem)
        {
            var productData = this._getProductById(Number(elem.data('cart-item')));

            if (!_.isUndefined(productData))
            {
                $(document).trigger('ajax:removeFromCart', {
                    productIds: [productData['product_id']]
                });
                var sections = ['cart'];

                setTimeout(function ()
                {
                    if (customerData.get('cart')().items.length == 0)
                    {
                        window.location.reload();
                    }
                }, 2000);

                if (window.location.href.indexOf(this.shoppingCartUrl) === 0)
                {
                    window.location.reload();
                }
            }
            this._customerData();
        },
        _estimateTotalsAndUpdateRatesCheckout: function ()
        {
            var serviceUrl, payload;
            var address = quote.shippingAddress();
            shippingService.isLoading(true);
            serviceUrl = resourceUrlManager.getUrlForEstimationShippingMethodsForNewAddress(quote);
            payload = JSON.stringify({
                    address: {
                        'street': address.street,
                        'city': address.city,
                        'region_id': address.regionId,
                        'region': address.region,
                        'country_id': address.countryId,
                        'postcode': address.postcode,
                        'email': address.email,
                        'customer_id': address.customerId,
                        'firstname': address.firstname,
                        'lastname': address.lastname,
                        'middlename': address.middlename,
                        'prefix': address.prefix,
                        'suffix': address.suffix,
                        'vat_id': address.vatId,
                        'company': address.company,
                        'telephone': address.telephone,
                        'fax': address.fax,
                        'custom_attributes': address.customAttributes,
                        'save_in_address_book': address.saveInAddressBook
                    }
                }
            );
            storage.post(
                serviceUrl, payload, false
            ).done(function (result) {
                rateRegistry.set(address.getCacheKey(), result);
                shippingService.setShippingRates(result);
            }).fail(function (response) {
                shippingService.setShippingRates([]);
                errorProcessor.process(response);
            }).always(function () {
                shippingService.isLoading(false);
            });
        }
    });
});

```

this code here render the template from 

```
app/design/frontend/MageBig/martfury/project01/Magento_Checkout/web/template/summary/item/details.html
```

and the code content is as below

```

<!-- ko foreach: getRegion('before_details') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
<div class="product-item-details">

    <div class="product-item-inner">
        <div class="product-item-name-block">
            <strong class="product-item-name" data-bind="html: $parent.name">
            </strong>
            <div class="details-qty-price-container">
                <div class="details-qty qty">
                    <label class="label" data-bind="i18n: 'Qty', attr: {for: 'cart-item-'+$parent.item_id+'-qty'}" style="display: none;">
                    </label>
                    <button data-bind="attr: {id: 'minus-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,'data-btn-minus': 'minus',},click:updateItemQtyCheckout" class="update-cart-item minus">-</button>
                    <input data-bind="attr: {id: 'cart-item-'+$parent.item_id+'-qty','data-cart-item': $parent.item_id,'data-item-qty': $parent.qty,'data-cart-item-id': $parent.product_sku}, value: $parent.qty"type="number"size="4"class="item-qty cart-item-qty" readonly>
                    <button data-bind="attr: {id: 'plus-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,'data-btn-plus': 'plus'},click:updateItemQtyCheckout" class="update-cart-item plus">+</button>
                    <button data-bind="attr: {id: 'update-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,title: $t('Update')}" class="update-cart-item" style="display: none"><span data-bind="i18n: 'Update'"></span>
                    </button>
                </div>
                <!-- ko foreach: getRegion('after_details') -->
                    <!-- ko template: getTemplate() --><!-- /ko -->
                <!-- /ko -->
            </div>
        </div>
        <div class="actions">
            <button data-bind="attr: {id: 'remove-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,'data-btn-remove': 'remove',},click:updateItemQtyCheckout" class="update-cart-item remove">
                <svg xmlns="http://www.w3.org/2000/svg" width="10.828" height="10.828" viewBox="0 0 10.828 10.828">
                    <g id="cross" transform="translate(1.414 1.414)">
                        <path id="Path_5049" data-name="Path 5049" d="M0,0,8,8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="2"/>
                        <line id="Line_204" data-name="Line 204" y1="8" x2="8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
                    </g>
                </svg>
            </button>
        </div>
    </div>

    <!-- ko if: (JSON.parse($parent.options).length > 0)-->
    <div class="product options" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}">
        <span data-role="title" class="toggle"><!-- ko i18n: 'View Details' --><!-- /ko -->
        </span>
        <div data-role="content" class="content">
            <strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko -->
            </strong>
            <dl class="item-options">
                <!--ko foreach: JSON.parse($parent.options)-->
                <dt class="label" data-bind="text: label">
                </dt>
                    <!-- ko if: ($data.full_view)-->
                    <dd class="values" data-bind="html: full_view">
                    </dd>
                    <!-- /ko -->
                    <!-- ko ifnot: ($data.full_view)-->
                    <dd class="values" data-bind="html: value">
                    </dd>
                    <!-- /ko -->
                <!-- /ko -->
            </dl>
        </div>
    </div>
    <!-- /ko -->
</div>
<!-- ko foreach: getRegion('item_message') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->

this code then render this file below in which you can see that the there is the code

click:updateItemQtyCheckout

which seems to refer to the function during which mini cart item is updated

app/design/frontend/MageBig/martfury/project/Magento_Checkout/web/template/summary/item/details.html
<!-- ko foreach: getRegion('before_details') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->
<div class="product-item-details">

    <div class="product-item-inner">
        <div class="product-item-name-block">
            <strong class="product-item-name" data-bind="html: $parent.name">
            </strong>
            <div class="details-qty-price-container">
                <div class="details-qty qty">
                    <label class="label" data-bind="i18n: 'Qty', attr: {for: 'cart-item-'+$parent.item_id+'-qty'}" style="display: none;">
                    </label>
                    <button data-bind="attr: {id: 'minus-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,'data-btn-minus': 'minus',},click:updateItemQtyCheckout" class="update-cart-item minus">-</button>
                    <input data-bind="attr: {id: 'cart-item-'+$parent.item_id+'-qty','data-cart-item': $parent.item_id,'data-item-qty': $parent.qty,'data-cart-item-id': $parent.product_sku}, value: $parent.qty"type="number"size="4"class="item-qty cart-item-qty" readonly>
                    <button data-bind="attr: {id: 'plus-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,'data-btn-plus': 'plus'},click:updateItemQtyCheckout" class="update-cart-item plus">+</button>
                    <button data-bind="attr: {id: 'update-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,title: $t('Update')}" class="update-cart-item" style="display: none"><span data-bind="i18n: 'Update'"></span>
                    </button>
                </div>
                <!-- ko foreach: getRegion('after_details') -->
                    <!-- ko template: getTemplate() --><!-- /ko -->
                <!-- /ko -->
            </div>
        </div>
        <div class="actions">
            <button data-bind="attr: {id: 'remove-cart-item-'+$parent.item_id,'data-cart-item': $parent.item_id,'data-btn-remove': 'remove',},click:updateItemQtyCheckout" class="update-cart-item remove">
                <svg xmlns="http://www.w3.org/2000/svg" width="10.828" height="10.828" viewBox="0 0 10.828 10.828">
                    <g id="cross" transform="translate(1.414 1.414)">
                        <path id="Path_5049" data-name="Path 5049" d="M0,0,8,8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="2"/>
                        <line id="Line_204" data-name="Line 204" y1="8" x2="8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
                    </g>
                </svg>
            </button>
        </div>
    </div>

    <!-- ko if: (JSON.parse($parent.options).length > 0)-->
    <div class="product options" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}">
        <span data-role="title" class="toggle"><!-- ko i18n: 'View Details' --><!-- /ko -->
        </span>
        <div data-role="content" class="content">
            <strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko -->
            </strong>
            <dl class="item-options">
                <!--ko foreach: JSON.parse($parent.options)-->
                <dt class="label" data-bind="text: label">
                </dt>
                    <!-- ko if: ($data.full_view)-->
                    <dd class="values" data-bind="html: full_view">
                    </dd>
                    <!-- /ko -->
                    <!-- ko ifnot: ($data.full_view)-->
                    <dd class="values" data-bind="html: value">
                    </dd>
                    <!-- /ko -->
                <!-- /ko -->
            </dl>
        </div>
    </div>
    <!-- /ko -->
</div>
<!-- ko foreach: getRegion('item_message') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!-- /ko -->

I try to put alert("Test") and console.log("Test"); to see if able to capture the code when the minicart product is being updated, unfortunately nothing happened,

I do not understand how the code click:updateItemQtyCheckout behave and how do I execute javascript code during this event happen

Any help is kindly appreciated whether in helping me understand knockout js or code fixing

1 Answer 1

0

I finally able to get the event for this, it is located at

app/design/frontend/MageBig/martfury/project01/Magento_Checkout/web/js/view/minicart.js

under the code

initialize: function () {
    var self = this,
        cartData = customerData.get('cart');

    this.update(cartData());
    cartData.subscribe(function (updatedCart) {
        console.log("This code will trigger when user add or remove item on mini cart")
        addToCartCalls--;
        this.isLoading(addToCartCalls > 0);
        sidebarInitialized = false;
        this.update(updatedCart);
        initSidebar();
    }, this);
    $('[data-block="minicart"]').on('contentLoading', function () {
        addToCartCalls++;
        self.isLoading(true);
    });

    if (
        cartData().website_id !== window.checkout.websiteId && cartData().website_id !== undefined ||
        cartData().storeId !== window.checkout.storeId && cartData().storeId !== undefined
    ) {
        customerData.reload(['cart'], false);
    }

    return this._super();
},

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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