#StackBounty: #magento2 #javascript #knockoutjs #requirejs-config.js How to load js file first in Magento 2

Bounty: 100

I’m using Magento 2 and I have a js file that was called like this:

default.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>
      <referenceContainer name="after.body.start">
          <block class="VendorModuleBlockAjaxLoginJs" template="Vendor_Module::login-ajax.phtml" name="login.ajax" as="login.ajax" before="head.components" ifconfig="loginpopup/general/enabled" />
      </referenceContainer>
    </body>
</page>

login-ajax.phtml

<script type="text/x-magento-init">
{
    "*": {
        "vm/loginajax"    : <?php echo $block->getJsOptions(); ?>
    }
} 

requirejs-config.js

var config = {
    map: {
        '*': {
            'vm/loginajax': 'Vendor_Module/js/login-ajax'
        }
    }
};

Vendor_Module/js/login-ajax

define([
    'jquery',
    'mage/translate',
    'jquery/ui',
    'mage/validation/validation',
    'vm/mycustom'
], function ($, $t) 

the js file size is 3KB , i noticed the js file is rendered not at the very beginning, how can i set the priority so this js file will load first?


Get this bounty!!!

#StackBounty: #magento2 #knockoutjs #datepicker Using Custom JS for magento 2 KO datepicker in checkout page error required field

Bounty: 50

I tried to add a custom datepicker with custom js in my Magento 2 checkout for delivery date, the custom js datepicker is showing and when i click the date it fills the value, but when i click next to go to the payment method i got an error This is a required field.

enter image description here

the html file:

<input id="shipping_date" class="input-text" type="text" data-bind="
        event: {change: userChanges},
        hasFocus: focused,
        value: value, 
        datepicker: true,
        attr: {
            name: inputName,
            placeholder: placeholder,
            'aria-describedby': noticeId,
            disabled: disabled
        }" readonly="true"/>
<div class="clearfix">
  <div id="cal1Container">
</div>

the js file:

define([
    'jquery',
    'ko',
    'Magento_Ui/js/form/element/abstract'
], function ($, ko, Component) {
    'use strict';
    return Component.extend({
        initialize: function () {
            this._super();
            var calendar = window.checkoutConfig.calendar;
            var storeId = window.checkout.storeId; 
            ko.bindingHandlers.datepicker = {
                init: function (element, valueAccessor, allBindingsAccessor) {
                    var $el = $(element); 

                    // custom DatePicker
                    YAHOO.namespace("shipping.calendar");
                    YAHOO.shipping.calendar.init = function() {
                        var options = {
                            mindate: calendar.first_day,
                            maxdate: calendar.last_day,
                            locale_weekdays: "1char",
                        };
                        YAHOO.shipping.calendar.cal1 = new YAHOO.widget.CalendarGroup(
                          "cal1",
                          "cal1Container", options,
                           {PAGES:2}
                        );  
                        var mySelectHandler = function(type,dateSelected,obj) {
                          var dates = dateSelected[0];
                                    var date = dates[0];
                                    var year = date[0], month = date[1], day = date[2];
                                    var date = year + "-" + month + "-" + day;
                                    document.getElementById('shipping_date').value = date;  
                        }; 

                             YAHOO.shipping.calendar.cal1.selectEvent.subscribe(mySelectHandler, YAHOO.shipping.calendar.cal1, true);
                        YAHOO.shipping.calendar.cal1.render();
                    }

                    YAHOO.util.Event.onDOMReady(YAHOO.shipping.calendar.init); 
                    // end custom DatePicker

                } 
            };

            return this;
        }
    });
});


Get this bounty!!!

#StackBounty: #magento2 #uicomponent #knockoutjs Magento 2 UI Component conflicts between observable value

Bounty: 50

I try to add UI Component to product item on product list due to difficult FE login for each item. But I was wondering when conflicts between components appeared. All components for each item has a unique name.

This is an example how I try to implement it:

Added div with scope to list.phtml and added script for each item:

<div class="test-component" data-bind="scope: 'test_<?= $_product->getId() ?>'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "test_<?= $_product->getId() ?>": {
                        "component": "Magento_Catalog/js/test-component",
                        "template" : "Magento_Catalog/test-component",
                        "config": {
                        }
                    }
                }
            }
        }
    }
</script>

Then I added JS Component test-component.js:

define([
    'jquery',
    'uiComponent',
    'ko'
], function ($, Component, ko) {
    return Component.extend({
        testObservable: ko.observable(1),

        initialize: function() {
            this._super();
        }
    });
});

Finally added HTML template test-component.html

<div>
    <input type="text"
           data-bind='value: testObservable'
           class="input-text qty" min="1"/>
</div>

As a result, fields display for each product and observable works but when I change it for one item it changes for all items:

enter image description here

The real example is much more complex but this is an example of a problem. Maybe UI components don’t a good solution?
As a solution, I can call some JS method on changing and set it to some observable object with the productId key but it looks weird when observable value shares between components.

Thanks.


Get this bounty!!!

#StackBounty: #magento2 #checkout #magento2.3 #knockoutjs Render getTemplate() in nested foreach

Bounty: 100

I am trying to update checkout page layout. What I want to do is to merge progress bar and checkout steps templates.

I have updated my app/code/Vendor/Module/view/frontend/web/template/onepage.html file and updated it like below.

    // Renders my progress bar template successfully. // To render step template, but not working // not working either

What I am trying to do is to display navigator step first and after step, there will be the content for particular step.

I have tried using $parent.getTemplate() to call template of parent foreach but its not working. I have also tried assigning a variable to getRegion('steps') foreach and then use step.getTemplate() but its not working either.

Does anyone have idea how can I achieve this?


Get this bounty!!!

#StackBounty: #magento2 #checkout #cart #knockoutjs #coupon-codes Apply bindings and subscribe on change of discount amount totals.tota…

Bounty: 50

in my checkout page when promo code is applied, I am updating a text using some calculation using knockoutjs

In my checkout page, on applying and removing promo code, it changes the discount key in totals.totals().items.
How to apply bindings and subscribe in knockoutjs,
so that I can call my function which I am calling from my HTML.

Magento_Checkout/web/template/summary/item/details.html

 <span class="tag-text">
    <!-- ko if: getFinalSale($parent)-->
      <u class="product-tag underline-bold-text checkout-final-sale" data-bind="text: getFinalSale($parent)"></u>
    <!-- /ko -->
</span>

I have written above code in details.html

and my js is

Magento_Checkout/web/js/view/summary/item/details.js

knockout js

  define([
   'uiComponent',
   'ko',
   'Magento_Checkout/js/model/totals'
    ], function (Component, ko, totals) {
   'use strict';
    var finalSaleData = window.checkoutConfig.items;

    return Component.extend({
     defaults: {
         template: 'Magento_Checkout/summary/item/details'
     },
    quoteItemData: quoteItemData,
    finalSaleData: finalSaleData,

    /**
     * @param {Object} quoteItem
     * @return {String}
     */

    getItems: function(item_id) {
        var itemElement = null;
        _.each(this.finalSaleData, function(element, index) {
            if (element.item_id == item_id) {
                itemElement = element;
            }
        });
        return itemElement;
    },
    getFinalSale : function (quoteItem) {
        var item = this.getItems(quoteItem.item_id);
        var temp_item = this.getTempItems(quoteItem.item_id);
        var tagText = '';

        if((((temp_item.price*temp_item.qty) - temp_item.discount_amount)/(item.base_old_price*temp_item.qty)) < 0.5){
            var tagText = 'Final Sale';
        }else{
            if(item.base_old_price && temp_item.price){
                // && item.price < item.price && item.base_old_price / item.price <= 0.5){
                if(((item.base_old_price - temp_item.price)/item.base_old_price)>0.5){
                    var tagText = 'Final Sale';
                }
            }
        }
        return tagText;
    }, 
  });
});

I am using var finalSaleData = window.checkoutConfig.items in my function getFinalSale.

How to make getFinalSale function run every time when window.checkoutConfig.items data is changed without refreshing the page.

1) How can i call getFinalSale on the change of totals.totals().items

2) The issue I am passing the $parent from my HTML and when the totals.totals().items the discount amount is changed for each item after applying promo code then how will I pass this $parent(quoteItem) from the very same js.

How to solve that.

The problem is, this runs only when the page reloads.

How to make getFinalSale function run every time the user applies promo code without refreshing the page so that my HTML gets updated too.

Basically Final Sale text needs to be shown on the basis of that logic in js code in getFinalSale function.

And also, data-bind="text: getFinalSale($parent) i am calling this from HTML and I am using subscribe also but then how i will pass $parent parameter from subscribing so that getFinalSale runs when this.totals changes everytime after applying coupon.

initialize: function(){
        this._super();
        this.totals.subscribe(function (data) {
          this.getFinalSale(data)
        }, this);
    } ,

The data parameter is not same as $parent which i passed it from html.
and it breaks the js.


Get this bounty!!!

#StackBounty: #magento2 #checkout #cart #knockoutjs #coupon-codes How to call a function on change of window.checkoutConfig data so tha…

Bounty: 50

in my checkout page when promo code is applied, I am updating a text using some calculation using knockoutjs

So, I am using window.checkoutConfig data in my js for some calculation.
the function works well when called from HTML, but it doesn’t run on itself when window.checkoutConfig data is changed.

Magento_Checkout/web/template/summary/item/details.html

 <span class="tag-text">
    <!-- ko if: getFinalSale($parent)-->
      <u class="product-tag underline-bold-text checkout-final-sale" data-bind="text: getFinalSale($parent)"></u>
    <!-- /ko -->
</span>

I have written above code in details.html

and my js is

Magento_Checkout/web/js/view/summary/item/details.js

knockout js

  define([
   'uiComponent',
   'ko',
   'Magento_Checkout/js/model/totals'
    ], function (Component, ko, totals) {
   'use strict';
    var finalSaleData = window.checkoutConfig.items;

    return Component.extend({
     defaults: {
         template: 'Magento_Checkout/summary/item/details'
     },
    quoteItemData: quoteItemData,
    finalSaleData: finalSaleData,

    /**
     * @param {Object} quoteItem
     * @return {String}
     */

    getItems: function(item_id) {
        var itemElement = null;
        _.each(this.finalSaleData, function(element, index) {
            if (element.item_id == item_id) {
                itemElement = element;
            }
        });
        return itemElement;
    },
    getFinalSale: function (quoteItem) {
        var item = this.getItems(quoteItem.item_id);
        var tagText = '';

        if((((item.price*item.qty) - item.discount_amount)/(item.base_old_price*item.qty))< 0.5){
            var tagText = 'Final Sale';
        }else{
            if(item.base_old_price && item.price){
                // && item.price < item.price && item.base_old_price / item.price <= 0.5){
                if(((item.base_old_price - item.price)/item.base_old_price)>0.5){
                    var tagText = 'Final Sale';
                }
            }
        }
        return tagText;
    },   
  });
});

I am using var finalSaleData = window.checkoutConfig.items in my function getFinalSale.

How to make getFinalSale function run every time when window.checkoutConfig.items data is changed without refreshing the page.

The problem is, this runs only when the page reloads.

How to make getFinalSale function run every time the user applies promo code without refreshing the page so that my HTML gets updated too.

Basically Final Sale text needs to be shown on the basis of that logic in js code in getFinalSale function.

How to achieve that.


Get this bounty!!!

#StackBounty: #magento2 #checkout #cart #knockoutjs #coupon How to update checkout/cart/ orders total when promo code is applied dynami…

Bounty: 50

I have changed my checkout/cart/ page promo code to ajax call so that it doesn’t get reloaded, while on the success of that ajax call, I have to update the total price summary dynamically without reloading.

How to achieve that.

enter image description here

Need to update this(price summary) as soon as user apply the promo code, I am using ajax instead of reloading the page as it was happening earlier.

I referred some links,

define([
'jquery',
'Magento_Checkout/js/model/cart/totals-processor/default',
'Magento_Checkout/js/model/quote',
'OtherDependencies'
], function ($,totalsProvider, quote){
  'use strict';
  //Your code here
  totalsProvider.estimateTotals(quote.shippingAddress());
});

How this code supposed to work as i dont have any shippingAddress here.

It just promo code and have to update the subtotal and order total with promo amount applied.


Get this bounty!!!