0

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?

1

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

  • Thanks for the reply. But, your solution is not working. – Rohan Hapani Jan 22 at 4:29
  • First, when page load kotemplate.js is call. After on button click, when popup open at that time, other js is called. So, I created ko.observable variable in kotemplate.js file and set value from other js. Then, need to access in kotemplate.js. – Rohan Hapani Jan 22 at 4:34
  • 1
    I need to see all your code to help with that, it sounds like you need to subscribe to that variable? The code I provided there does work I've tested it twice so maybe you're changing something? – Ben Crook Jan 22 at 9:44
  • Okay. Let me check again. – Rohan Hapani Jan 22 at 9:46
  • 1
    To be honest I'm not entirely sure why it's a function, I tried it without the parenthesis and it didn't work. Without looking into it I can only presume the component needs to initialise for you to have access to it's properties. If it works without the parenthesis for you then it should be fine. Glad I could help. – Ben Crook Jan 22 at 11:17

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.