Вопрос

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.

Это было полезно?

Решение

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с magento.stackexchange
scroll top