X

Geertjan's Blog

  • February 12, 2016

Intermodular Communication in Oracle JET (Part 2)

Geertjan Wielenga
Product Manager

In the previous blog entry, you were shown how to create and access global variables in Oracle JET. The global variables were defined in the root viewModel, i.e., within 'main.js' and accessed from HTML files via the $root (which could also be $parent) variable. In this blog entry, let's suppose that you need to get hold of those root variables from within the JavaScript side of your JET module instead.

To get started,  you are going to need to add a containing DIV element around your two ojModule bound DIVs, while making sure you give it an ID:

<div id="mainContent">
<div id="homeContent" data-bind="ojModule: {name: 'home'}"></div>
<div id="responseContent" data-bind="ojModule: {name: 'response'}"></div>
</div>

"By the way, you should never have a DIV without an ID," JB Brock tells me. "It's an accessibility pitfall if you do."



Next, in main.js, you should always "applyBindings" to a specific DOM element. The way I had it before, it's a global binding, and you would run into nested binding errors if you tried to do any other applyBindings in that same page. The change is as follows:

$(document).ready(
function ()
{
ko.applyBindings(
new RootViewModel(),
document.getElementById('mainContent'));
}
);

Everything has been set up correctly and now you can access the root viewModel as follows:

ko.dataFor(document.getElementById('mainContent')

For example, here is the above syntax in "response.js":

define(['ojs/ojcore', 'knockout'
], function (oj, ko) {
function responseContentViewModel() {
var self = this;
var rootViewModel = ko.dataFor(document.getElementById('mainContent'));
self.userName = rootViewModel.userName;
self.userCity = rootViewModel.userCity;
self.userState = rootViewModel.userState;
}
return responseContentViewModel;
});

And now, instead of needing to refer to $root in your HTML view, you can use the properties defined above in the JavaScript side of your JET module:

<h2>User Details</h2>
<p>Name: <span data-bind="text: userName"></span></p>
<p>City: <span data-bind="text: userCity"></span></p>
<p>State: <span data-bind="text: userState"></span></p>

When the global variables change, thanks to the user inputting new values in "home.html", the "response.html" will automatically be updated.

An extra tip, which works too, is that if you have ID's on the ojModule binding DIVs, you are able to get the data in each of those JET modules as well. That means you have true cross modular communication, without the root intermediary, like this in "response.js":

ko.dataFor(document.getElementById('homeContent'))

Further reading on "ko.dataFor" (and the related "ko.contextFor"):

http://knockoutjs.com/documentation/unobtrusive-event-handling.html

Join the discussion

Comments ( 3 )
  • Miguel Durazo Wednesday, January 25, 2017

    What if i have a module and inside of it i use 2 more modules, how can i have global information on the parent module and its children?


  • guest Thursday, March 16, 2017

    "By the way, you should never have a DIV without an ID," JB Brock tells me. "It's an accessibility pitfall if you do."

    With respect, he's wrong. These days, in fact, it's much preferable to never use ids on anything at all except where absolutely necessary (e.g. label-for), and use classes instead even for singletons. Accessibility tools work just fine with that, and there's far less chance of introducing cryptic bugs by accidentally duplicating ids on the same page.


  • Geertjan Wielenga Thursday, March 16, 2017

    OK, great.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services