Firstly I am new to knockoutjs and I have started to develop an application using knockout-amd-helpers and we are using require.js to load modules. I am facing the following issue with publish subscribe:
My main page has two section, navigation and mainContainer, both loaded as modules (external html templates and js files) and I am setting the name of the modules with observable so it can be replaced dynamically. In the mainContainer, there is a tree and if the user clicks on any node of the tree then two things should happen. 1. The entire mainContainer module needs to be replaced with a different module called 'detail' in the same div tag. 2. Based on the node in the tree, that the user has clicked in the mainContainer, I need to pass the value as a parameter to this 'detail' module.
I figured I can achieve 1. by setting the module name as an observable and 2. by publishing the node value in the mainContainer on a particular topic and in the detail module I need to subscribe to that topic and pass to the module with 'data' attribute.
So in the onclick event of the node of the tree, I am publishing the node value, and changing the module name value in the observable which successfully replaces the mainContainer with the detail module. However in the detail module, even though I am subscribing to the topic that was published, it fails to get hold of the value since this subscribe takes place in the detail module, and the detail module has loaded once the user has clicked the node and so, after publish has already taken place in the mainContainer. So I am subscribing to a topic for which publish has already taken place and so wont be able to get past published values.
I have a temporary work around by calling the subscribe on the root module (parent of detail module), but it seems to me a dirty solution and ideally I would like to keep this logic in the detail module itself.
This is more of a design problem so I am not posting the code, but I was wondering if anybody can comment on whether I should approach this differently or if there is a technical solution to it.
Thanks
You could consider passing the extra information as initialization data to your "detail" module.
If your module returns a function (constructor), then the value will be passed to the function itself. If your module returns an object, then it will be passed to the initialize
function.
So, instead of binding against just an observable module name, you can bind against an observable that holds a module binding config object.
You would populate it like:
this.currentModule({
name: "details",
data: someData
});
With a binding like:
<div data-bind="module: currentModule"></div>
Here is a sample: http://jsfiddle.net/rniemeyer/ctx083w3/