5

I need the product URL for each product in the checkouts cart.

Therefore I want to edit vendor/magento/module-checkout/view/web/templates/summary/item/details.html and add my custom method there, lets call it myMethod.

This is how my code looks like right <strong class="product-item-name" data-bind="text: $parent.name, myMethod:{}"></strong>.

However, in a console, i have the log that there's no function called myMethod. Logic!

How can I create myMethod in Order to let it work? Where do I need to inject my JS?

What do I want to do? For legal reasons, I need the URL of the product. I want KO to do my request by calling an ajax file that returns the URL of the product and then links it. The final code in details.html will look like this:

<a class="product-item-name" data-bind="text: $parent.name, myMethod:{}"></a>

In onepage.phtml I've added the following to test, but it does not work:

<script type="text/javascript">
    require([
        'jquery',
        'ko'
    ], function($, ko) {
        ko.bindingHandlers.myMethod = {
            init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
                jQuery(this).css("background-color","red");
            }
        };
    });
</script>

How can I achieve what I what?

3 Answers 3

10

For Magento to apply the bindings you need to add your Knockout JS using the UI Components like so:

Inside the PHTML Template file

Pay extra attention to example-scope as it needs to match the scope of the markup.

Component links to your JS file, and template links to your HTML (or PHTML) file that contains the data-binds (and scope).

<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
            "components": {
                "example-scope": {
                    "component": "VENDOR_MODULE/js/name-of-your-js-file",
                    "template": "Magento_Checkout/summary/item/details"
                }
            }
        }
    }
}
</script>

<div data-bind="scope: 'example-scope'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

Inside your JS file

define(['jquery', 'ko'], function($, ko) {
    return function(config) {
        // YOUR SCRIPT HERE
    }
});
8
  • Hi in case i don't use script with x-magento-init , can i use bind ko to element inside js ? Ex: specific id element in js code to binding data ko.applyBinding(data, '#id_element')
    – mrtuvn
    Dec 1, 2016 at 17:39
  • I don't think you can use applyBindings within Magento 2, this was the first thing I tried but it stopped the KO in Magento from working.
    – Ben Crook
    Dec 2, 2016 at 9:37
  • @BenCrook, I did same but i don't get output. Oct 26, 2017 at 10:49
  • @Sarfaraj Have you cleared browser cache and Magento cache? You may possibly need to redeploy static content or setup symlinks again depending on your workflow.
    – Ben Crook
    Oct 26, 2017 at 10:52
  • @BenCrook, yes i have applied deploy commands and also clear browser cache. Oct 26, 2017 at 10:53
2

In order to achieve that first, you should modify:

details.html:

<div data-bind="text: someAction($parent)"></div>

This an entry point for debbuging. You have to find corresponding js file. In Magento\Checkout\...\web\js\...\details.js you should add this someAction() method. Here you can put console.log() and searching around. I was modyfying OneStepCheckout by Magestore, but I bet you can use that (add it inside below other functions), one or make some modifications:

details.js:

 /**
         * Method gets product object basing on quoteItem and quote object.
         *
         * @param {object} quoteItem
         *
         * @return {object}
         */

        getProductOfQuoteItem: function(quoteItem) {
            var quoteItemId = quoteItem.item_id;
            var quoteItemCollection = quote.getItems();
            for (var i in quoteItemCollection) {
                if (quoteItemCollection[i].item_id == quoteItemId) {
                   return quoteItemCollection[i];
                }
            }
       },

Here you should have product object, but it has only part of data. If you don't have information you need you can add them using observer: on sales_quote_item_set_product

and in observer you can add data more or less like this (I was adding some category data):

class addDataToQuoteItem implements ObserverInterface
{
    /**
     * @var \Magento\Catalog\Api\CategoryRepositoryInterface
     */
    private $categoryRepository;


    /**
     * Di.
     *
     * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepositoryInterface
     */
    public function __construct
    (
        CategoryRepositoryInterface $categoryRepositoryInterface
    )
    {
        $this->categoryRepository = $categoryRepositoryInterface;
    }


    /**
     * Method adds custom data to every quote item object.
     *
     * @param \Magento\Framework\Event\Observer $observer
     */
    public function execute(Observer $observer)
    {
        $product = $observer->getProduct();
        /** @var $product \Magento\Catalog\Api\Data\ProductInterface */
        $categoryIds = $product->getCategoryIds();

        $quoteItem = $observer->getQuoteItem();
        /** @var $quoteItem \Magento\Quote\Api\Data\CartItemInterface */

        //To inject it as attribute, not using setData() you need xml, provided below
        $quoteItem->setCategoryIds($product->getCategoryIds());

        //That way you don't need any xml
        $quoteItem->setData('categoryData', $categoryIds);
    }
}

and xml if using first method in observer - etc\catalog_attributes.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/catalog_attributes.xsd">
<group name="quote_item">
    <attribute name="category_ids"/>
</group>

I was doing all this on module modifing default Magento_Checkout (aparat observer - it works on native event), so I can't promise that it will work at once, but you have some starting point to work it out.

2

Thanks for your good answer @Ben Crook.

Add another way to add the template:

<script type="text/x-magento-init">
{
    "*": {
        "Magento_Ui/js/core/app": {
            "components": {
                "example-scope": {
                    "component": "VENDOR_MODULE/js/name-of-your-js-file",
                    "customMessage": "<?php echo __("Testing message.");?>"
                }
            }
        }
    }
}
</script>

<div data-bind="scope: 'example-scope'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

In your js file, we can declare the template:

VENDOR_MODULE/js/name-of-your-js-file

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

    return Component.extend({
        defaults: {
            template: 'VENDOR_MODULE/yourtemp',
            customMessage: 'Default Text Ready'
        },

        initialize: function () {
            this._super(); // Remember to add this
            console.log(this.customMessage); // Will print "Testing message."
            ......
        }
    });
});

Your template should be under VENDOR_MODULE/view/frontend/web/template/yourtemp.html

3

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.