3

I'm trying to implement a "block loader" animation on the cart summary element on the cart page while the cart totals are loading.

The template file which loads this is Magento_Checkout/templates/cart/totals.phtml. It loads the totals with knockout.js and reads the html templates from checkout_cart_index.xml:

<!-- ko template: getTemplate() --><!-- /ko -->
<script type="text/x-magento-init">
        {
            "#cart-totals": {
                "Magento_Ui/js/core/app": <?= /* @escapeNotVerified */ $block->getJsLayout() ?>
            }
        }
</script>

EDIT

Magento has a default loader on the cart totals when the customer clicks on the estimated shipping country, but I find this functionality useless, so I've disabled it.

I'm trying to show the loader animation when the cart page is loading. There is always a delay before the totals show up, so the my goal is to show a loader here before they are fully loaded.

I've made several attempts in Magento_Checkout::templates/cart/totals.phtml

Attempt 1 - through x-magento-init script

<div id="cart-totals" class="cart-totals" data-bind="scope:'block-totals'">
    <!-- ko template: getTemplate() --><!-- /ko -->
    <script type="text/x-magento-init">
        {
            "#cart-totals": {
                "Magento_Ui/js/core/app": <?= /* @escapeNotVerified */ $block->getJsLayout() ?>
            },
            "*": { // I tried with #cart-totals here as well
                "Magento_Ui/js/block-loader": "<?= /* @escapeNotVerified */ $block->getViewFileUrl('images/loader-2.gif') ?>"
            }
        }
    </script>
</div>

Attempt 2 - by triggering processStart on the element

<div id="cart-totals" class="cart-totals" data-bind="scope:'block-totals'" data-mage-init='{"loader": {}}'>
    <!-- ko template: getTemplate() --><!-- /ko -->
    <script type="text/x-magento-init">
        {
            "#cart-totals": {
                "Magento_Ui/js/core/app": <?= /* @escapeNotVerified */ $block->getJsLayout() ?>
            }
        }
    </script>
</div>
<script>
    require([
        'jquery',
        'domReady!'
    ], function ($) {

        $('#cart-totals').trigger('processStart');

    })
</script>

Attempt 3 - data-mage-init

<div id="cart-totals" class="cart-totals" data-bind="scope:'block-totals'" data-mage-init='{"loader": {}}'>
    <!-- ko template: getTemplate() --><!-- /ko -->
    <script type="text/x-magento-init">
        {
            "#cart-totals": {
                "Magento_Ui/js/core/app": <?= /* @escapeNotVerified */ $block->getJsLayout() ?>
            }
        }
    </script>
</div>

Each attempt failed. It just doesn't show the loader.

What am I missing here?

3
+50

Did you want to add loader into templates/cart/totals.phtml These some ways to add loader spinner into block or page.

1 Use: <div data-bind="blockLoader: isLoadding"> /** Block Content HTML */ </div>,

with this option you should add isLoadding : ko.observable(false) into your Component

Example: Block XML Define

<block class="Magento\Framework\View\Element\Template" name="block-name"
                       template="Namespace_ModuleName::templates.phtml">
    <arguments>
        <argument name="jsLayout" xsi:type="array">
            <item name="components" xsi:type="array">
                <item name="scope_name" xsi:type="array">
                    <item name="component" xsi:type="string">Namespace_ModuleName/js/componentjsfile</item>
                </item>
            </item>
        </argument>
    </arguments>
 </block>

Block templates.phtml CODE

<div id="abc-def" data-bind="scope: 'scope_name'">
    <div class="product-wizard-selections" data-bind="blockLoader: isLoading">
        <div class="cart table-wrapper">
               HTML CONTENT
        </div>
    </div>
</div>

Script

<script type="text/x-magento-init">
    {
        "#abc-def": {
              "Magento_Ui/js/core/app":  <?php /* @escapeNotVerified */ echo $block->getJsLayout(); ?>
        }
    }
</script>

Javascript code: Namespace_ModuleName/js/componentjsfile

define([
    'uiComponent',
    'ko'
], function (Component, ko){
    return Component.extend({
        defaults: {
            addToCartTitle: 'Add To Cart'
        },
        isLoading: ko.observable(false),
        initObservable: function () {
              this._super();
              this.isLoading(true);
        }
    });
});

2: With <div class="loader"> using rjsResolver

js file named "Namespace_ModuleName/js/abc"

define([
    'rjsResolver',
], function (resolver) {
    'use strict';

    /**
     * Removes provided loader element from DOM.
     *
     * @param {HTMLElement} $loader - Loader DOM element.
     */
    function hideLoader($loader) {
        let defaultValue = this;
        $loader.parentNode.removeChild($loader);
    }

    /**
     * Initializes assets loading process listener.
     *
     * @param {Object} config - Optional configuration default data after loaded component
     * @param {HTMLElement} $loader - Loader DOM element.
     */
    function init(config, $loader) {
        resolver(hideLoader.bind(config, $loader));
    }

    return init;
});

PHTML file

<div id="block-loader-id" data-role="abc-loader" class="loading-mask" data-mage-init='{"Namespace_ModuleName/js/abc": {}}'>
    <div class="loader">
        <img src="<?= /* @escapeNotVerified */ $block->getViewFileUrl('images/loader-1.gif') ?>"
             alt="<?= /* @escapeNotVerified */__('Loading...') ?>" style="position: absolute;">
    </div>
</div>
<script>
    require([
        'mage/url',
        'Magento_Ui/js/block-loader'
    ], function (url, blockLoader) {
        blockLoader("<?= /* @escapeNotVerified */ $block->getViewFileUrl('images/loader-1.gif') ?>");
        return url.setBaseUrl('<?= /* @escapeNotVerified */ $block->getBaseUrl() ?>');
    });
</script>
  • Thank you for your detailed answer. It helped me understand how the loader works and I managed to implement it. – Lez Oct 4 '18 at 18:59
0

Cart totals has block loader by default.

It could be activated for example, as soon as you change a country in the Estimate shipping section. In fact, first the shipping costs are recalculated and its block loader is visible. As soon as the shipping is done it sends the signal for the totals to be recalculated and this block loader is visible at that moment.

As far as calling a loader in general, it could be as simple as adding this code inside the script <script type="text/x-magento-init">

    "#your-target-element": {
        "Magento_Ui/js/core/app": <?= /*YOUR JSON HERE usually acquired as $block->getJsLayout() */ {"a": "b", "c": "d"} ?>
    },
    "*": {
        "Magento_Ui/js/block-loader": "<?= /* @escapeNotVerified */ $block->getViewFileUrl('images/loader-1.gif') ?>"
    }

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.