Magento 2 : Access ko observable variable into other js file
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?
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);
}