Magento – Magento 2: Can’t call parent function in JS / knockout file

javascriptknockoutjsmagento2

I'm having trouble receiving the return value from a function in the parent file.

As you can see in Magento_Tax/js/view/checkout/summary/shipping.js, it's calling functions in the (grand)parent file (Magento_Checkout/js/view/summary/abstract-total.js – getFormattedPrice() ) but I'm receiving a JS error when I try to call this.getValue() in the parent file (this.getValue() is not a function).

Can anyone spot why I can't call this.getValue()?

Magento_Checkout/js/view/summary/shipping.js
(Parent file – I haven't touched this file apart from adding in the string return value for demo purposes).

define(
[
'ko',
'jquery',
'Magento_Checkout/js/view/summary/abstract-total',
'Magento_Checkout/js/model/quote'
],
function (ko, $, Component, quote) {
    return Component.extend({
        defaults: {
            template: 'Magento_Checkout/summary/shipping'
        },
        quoteIsVirtual: quote.isVirtual(),
        totals: quote.getTotals(),

        getShippingMethodTitle: function() {
            if (!this.isCalculated()) {
                return '';
            }
            var shippingMethod = quote.shippingMethod();
            return shippingMethod ? shippingMethod.carrier_title + " - " + shippingMethod.method_title : '';
        },

        isCalculated: function() {
            return this.totals() && this.isFullMode() && null != quote.shippingMethod();
        },

        getValue: function() {

            return 'this is the value I want to see in the #Magento_Tax/checkout/summary/shipping.html';

        }

    });
  }
);

Magento_Tax/js/view/checkout/summary/shipping.js
( I added just the newVar: ko.observable(this.getValue()) )

define(
[   
'ko',
'jquery',
'Magento_Checkout/js/view/summary/shipping',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/step-navigator'
],
function (ko, $, Component, quote, stepNavigator ) {
    var displayMode = window.checkoutConfig.reviewShippingDisplayMode;

    return Component.extend({
        defaults: {
            displayMode: displayMode,
            template: 'Magento_Tax/checkout/summary/shipping'
        },


        newVar: ko.observable(this.getValue()),


        isBothPricesDisplayed: function() {
            return 'both' == this.displayMode
        },
        isIncludingDisplayed: function() {
            return 'including' == this.displayMode;
        },
        isExcludingDisplayed: function() {
            return 'excluding' == this.displayMode;
        },
        isCalculated: function() {
            return this.totals() && this.isFullMode() && null != quote.shippingMethod();
        },
        getIncludingValue: function() {
            if (!this.isCalculated()) {
                return this.notCalculatedMessage;
            }
            var price =  this.totals().shipping_incl_tax;
            return this.getFormattedPrice(price);
        },
        getExcludingValue: function() {
            if (!this.isCalculated()) {
                return this.notCalculatedMessage;
            }
            var price =  this.totals().shipping_amount;
            return this.getFormattedPrice(price);
        }
    });
}
);

Magento_Tax/checkout/summary/shipping

// This is what I want to update with the return value from getValue()

<span data-bind="text: newVar() "></span>

...

Best Answer

From my understanding, to set the observable the way Magento uses knockout you would have to create an initialize function starting with this._super(); which will allow to call the parents.

define(
[   
'ko',
'jquery',
'Magento_Checkout/js/view/summary/shipping',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/step-navigator'
],
function (ko, $, Component, quote, stepNavigator ) {
    var displayMode = window.checkoutConfig.reviewShippingDisplayMode;

    return Component.extend({
        defaults: {
            displayMode: displayMode,
            template: 'Magento_Tax/checkout/summary/shipping'
        },

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

            this.newVar = ko.observable(this.getValue());
        },


        ...


    });
}
);

You should then be able to call the parents from anywhere in the code after the initialize function.

Also data-bind should be:

<span data-bind="text: newVar"></span>

Useful tips for using this:

If the need comes to access this from inside computed observables or keeping track of it using function overriding the this variable, you may simply use the appoach below.

self = this;
self.firstName = ko.observable('Some');
self.lastName = ko.observable('One');
self.fullName = ko.computed(function() {
    return self.firstName() + " " + self.lastName();
});

To pass this or any variable inside of a computed observable:

this.fullName = ko.computed(function() {
    return this.firstName() + " " + this.lastName();
}, this); //PASSED VARIABLE
Related Topic