Question

I`m trying to load a custom script after a custom-template for minicart items is rendered.

I created a javascript file vendor\module\view\frontend\web\js\test.js:

define('jquery', function($) {

    alert('Here');

});

and added it to my requirejs-config.js:

var config = {
    map: {
        '*': {
            'Magento_Checkout/template/minicart/item/default.html':
                'Vendor_Module/template/minicart/item/default.html',
            test: 'Vendor_Module/js/test'
        }
    }
};

No I try to run it after the rendering in my default.html with:

<div class="test" afterRender="test"></div>

But the console just outputs:

test is not defined

I really would appreciate any help on this. Why is the script not loaded?

For clarification: Vendor and Module are of course placeholders here.

Était-ce utile?

La solution

The afterRender method calls the specified method (test) of your component. So for your case you must define the test method inside the minicart component. You must add a mixin for the vendor/magento/module-checkout/view/frontend/web/js/view/minicart.js and add the test method or completely change the renderer component to define a new method. Here is simple example with overwriting a renderer component in custom module:

Here is complete code of example on GitHub.

Set custom template and custom component where we can define out test method:

app/code/MageWorx/UpdateMinicart/view/frontend/layout/checkout_cart_sidebar_item_renderers.xml

<?xml version="1.0"?>
<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="item.renderer" xsi:type="array">
                                    <item name="config" xsi:type="array">
                                        <item name="component" xsi:type="string">MageWorx_UpdateMinicart/js/minicart/item/default</item>
                                        <item name="template" xsi:type="string">MageWorx_UpdateMinicart/minicart/item/default</item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

Update regular template (add a custom div with afterRender binding):

app/code/MageWorx/UpdateMinicart/view/frontend/web/template/minicart/item/default.html

<li class="item product product-item" data-role="product-item">
    <div class="test" afterRender="$parent.test"></div>
    <div class="product">
        <!-- ko if: product_has_url -->
        <a data-bind="attr: {href: product_url, title: product_name}" tabindex="-1" class="product-item-photo">
            <!-- ko foreach: $parent.getRegion('itemImage') -->
            <!-- ko template: {name: getTemplate(), data: item.product_image} --><!-- /ko -->
            <!-- /ko -->
        </a>
        <!-- /ko -->
        <!-- ko ifnot: product_has_url -->
        <span class="product-item-photo">
            <!-- ko foreach: $parent.getRegion('itemImage') -->
            <!-- ko template: {name: getTemplate(), data: item.product_image} --><!-- /ko -->
            <!-- /ko -->
        </span>
        <!-- /ko -->

        <div class="product-item-details">
            <strong class="product-item-name">
                <!-- ko if: product_has_url -->
                <a data-bind="attr: {href: product_url}, html: product_name"></a>
                <!-- /ko -->
                <!-- ko ifnot: product_has_url -->
                <!-- ko text: product_name --><!-- /ko -->
                <!-- /ko -->
            </strong>

            <!-- ko if: options.length -->
            <div class="product options" data-mage-init='{"collapsible":{"openedState": "active", "saveState": false}}'>
                <span data-role="title" class="toggle"><!-- ko i18n: 'See Details' --><!-- /ko --></span>

                <div data-role="content" class="content">
                    <strong class="subtitle"><!-- ko i18n: 'Options Details' --><!-- /ko --></strong>
                    <dl class="product options list">
                        <!-- ko foreach: { data: options, as: 'option' } -->
                        <dt class="label"><!-- ko text: option.label --><!-- /ko --></dt>
                        <dd class="values">
                            <!-- ko if: Array.isArray(option.value) -->
                            <span data-bind="html: option.value.join('<br>')"></span>
                            <!-- /ko -->
                            <!-- ko ifnot: Array.isArray(option.value) -->
                            <span data-bind="text: option.value"></span>
                            <!-- /ko -->
                        </dd>
                        <!-- /ko -->
                    </dl>
                </div>
            </div>
            <!-- /ko -->

            <div class="product-item-pricing">
                <!-- ko if: canApplyMsrp -->

                <div class="details-map">
                    <span class="label" data-bind="i18n: 'Price'"></span>
                    <span class="value" data-bind="i18n: 'See price before order confirmation.'"></span>
                </div>
                <!-- /ko -->
                <!-- ko ifnot: canApplyMsrp -->
                <!-- ko foreach: $parent.getRegion('priceSidebar') -->
                <!-- ko template: {name: getTemplate(), data: item.product_price, as: 'price'} --><!-- /ko -->
                <!-- /ko -->
                <!-- /ko -->

                <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>

            <div class="product actions">
                <!-- ko if: is_visible_in_site_visibility -->
                <div class="primary">
                    <a data-bind="attr: {href: configure_url, title: $t('Edit item')}" class="action edit">
                        <span data-bind="i18n: 'Edit'"></span>
                    </a>
                </div>
                <!-- /ko -->
                <div class="secondary">
                    <a href="#" data-bind="attr: {'data-cart-item': item_id, title: $t('Remove item')}"
                       class="action delete">
                        <span data-bind="i18n: 'Remove'"></span>
                    </a>
                </div>
            </div>
        </div>
    </div>
</li>

Define the component having test function (we just logging a dummy string inside):

app/code/MageWorx/UpdateMinicart/view/frontend/web/js/minicart/item/default.js

define(
    [
        'uiComponent',
        'jquery'
    ],
    function (
        Component,
        $
    ) {
        'use strict';

        return Component.extend({
            test: function () {
                console.log('HERE I\'M');
                // $('#test').doSomething();
            }
        });
    }
);

Here is output on the frontend with 2 items added in minicart:

example output

Here is some clarification for "why test is not defined" error from your example:

When you put the test method in the afterRender binding inside template, the ko calling some anonymous function which binds an actual context and trying to call method you pass:

(function anonymous($context,$element
) {
with($context){with($data||{}){return{'afterRender':function(){return test }}}}
})

An actual context in that case (item renderer in cart) is Window which has no method test:

context example

The $parent for this context is our component:

parent context example view

Another available parents could be seen using the $parents keyword and we can access them using $parents[n] call inside the afterRender binding. The $data variable has all data about current cart item:

parents and $data

Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top