Question

I want to access ko observable variable from one js file to other js file. I apply some logic using below way. But, it's return undefined.

kotemplate.js :

define([
    'jquery',
    'uiComponent',
    'ko'
], function($,Component,ko) {
    "use strict";
    return Component.extend({
            defaults:{
                temp: ko.observable(0)
            },
            initialize: function () {
                self = this;
                this._super();
            },
            addCustomOptionsVal : function(temp) {
                 this.temp = temp;
                 console.log(this.temp);
            }
    });
});

price-options.js : (In my module js file)

define([
    "jquery",
    "priceUtils",
    "Vendor_Module/js/kotemplate",
    "priceOptions",
    "jquery/ui"
], function($, utils,kotemplate){
    "use strict";
    $.widget("vendormodule.priceOptions", $.mage.priceOptions, {

        /**
         * Custom option change-event handler
         * @param {Event} event
         * @private
         */
        _onOptionChanged: function onOptionChanged(event) {
            var changes,
                option = $(event.target),
                handler = this.options.optionHandlers[option.data('role')];

            option.data('optionContainer', option.closest(this.options.controlContainer));

            if (handler && handler instanceof Function) {
                changes = handler(option, this.options.optionConfig, this);
            } else {
                changes = defaultGetOptionValue(option, this.options.optionConfig,this.options.priceFormatJson);
            }
            $(this.options.priceHolderSelector).trigger('updatePrice', changes);
        }
    });

    /**
     * Custom option preprocessor
     * @param  {jQuery} element
     * @param  {Object} optionsConfig - part of config
     * @return {Object}
     */
    function defaultGetOptionValue(element, optionsConfig,priceFormatJson) {
        var changes = {},
            optionValue = element.val(),
            optionId = utils.findOptionId(element[0]),
            optionName = element.prop('name'),
            optionType = element.prop('type'),
            optionConfig = optionsConfig[optionId],
            optionHash = optionName,
            optionPriceTax = {};

        switch (optionType) {
            case 'text':
            case 'textarea':
                changes[optionHash] = optionValue ? optionConfig.prices : {};
                break;

            case 'radio':
                if (element.is(':checked')) {
                    changes[optionHash] = optionConfig[optionValue] && optionConfig[optionValue].prices || {};
                    var custom_option_title = element.parents('.control').prev().find('span').html();
                    kotemplate.addCustomOptionsVal(custom_option_title); //want to set custom_option_title value in temp variable from here
                }
                break;

            case 'select-one':
                changes[optionHash] = optionConfig[optionValue] && optionConfig[optionValue].prices || {};
                break;

            case 'select-multiple':
                _.each(optionConfig, function (row, optionValueCode) {
                    optionHash = optionName + '##' + optionValueCode;
                    changes[optionHash] = _.contains(optionValue, optionValueCode) ? row.prices : {};
                });
                break;

            case 'checkbox':
                optionHash = optionName + '##' + optionValue;
                changes[optionHash] = element.is(':checked') ? optionConfig[optionValue].prices : {};
                break;

            case 'file':
                // Checking for 'disable' property equal to checking DOMNode with id*="change-"
                changes[optionHash] = optionValue || element.prop('disabled') ? optionConfig.prices : {};
                break;
        }
        window.custom_option_arr = optionListData;
        return changes;
    }

    return $.vendormodule.priceOptions;
});

How to get value of kotemplate.temp and set value in that?

Was it helpful?

Solution

Quick solution

Change kotemplate.temp to kotemplate.temp(), when getting the value from a KO observable you need to include the parenthesis. This method is much shorter but isn't quite as easy to figure out for developers not used to UI components.

Parent File

define([
    'uiComponent',
    'ko'
], function(Component,ko) {
    "use strict";
    return Component.extend({
        defaults:{
            temp: ko.observable(0)
        }
    });
});

Child File

require([
    'Magento_Theme/js/parent',
], function(parent) {
    parent().temp();
});

More verbose method

This method involves more code but should be easier for new developers to pick up, create your own getter function:

Parent file

define([
    'uiComponent',
    'ko'
], function(Component,ko) {
    "use strict";
    return Component.extend({
        defaults:{
            temp: ko.observable(0)
        },

        getTemp: function() {
            return this.temp();
        }
    });
});

Child file

require([
    'Magento_Theme/js/parent',
], function(parent) {
    parent().getTemp();
});

Subscribing to the parent file's observable

If you need to subscribe to the observable for when it changes you can do this:

parent().temp.subscribe(function(value) {
    console.log('The new value of temp is' + value);
});

To test this I just increased the observable value by 1 every 2 seconds.

initialize: function() {
    this._super();
    var self = this;

    window.setInterval(function() {
        var newValue = self.temp() + 1;
        self.temp(newValue);
    }, 2000);
}

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top