After reading the documentation about activators, I am still confused about how to use activators. What I am trying to do is simple:
I have defined a requireJS module called global. When I use this module in other modules, it's activate function is not called. I need it do be.
If I load a module using compose:, activate functions fire just fine. But if I just load it as an AMD module, they don't. This is all I want to fix.
Note: My module is a singleton, and I only need activate to run once actually, so I tried something like this, which doesn't work, my shell.js
define(['plugins/router', 'durandal/app', 'plugins/ajax','durandal/global'], function (router, app,ajax,global) {
var vm = {};
vm.global = global;
vm.activate= function () {
return vm.rebuildRouter();
//not sure what this does, does it return a promise, does it run global's activate, does it hook up global so it activates at a later time, and if so when?
global.activator.activateItem(global); //I created an activator and called in activator inside global. Since its a singlton I think I only need one?
//Since I wasn't sure how to use activators I had to do this instead:
var promise = global.activate();
return promise;
//which works only the first time
}
I'd appreciate it if someone could explain this activators business to me. I use activate all the time with compose, and that works the way I want. I just don't understand what I need to do to get it to work as described above, and can't find a simple example that shows how to get any js module to behave the same way.
An activator is a special computed obseravble whose write function enforces the activation lifecycle when its value tries to change.
canDeactivate
is called on the current valuecanActivate
is called on the value trying to be setdeactivate
is called on the current valueactivate
is called on the value trying to be setUsing an activator is done to force some object to fire off these events when its value changes, and block the change if canDeactivate
or canActivate
return false
.
It does not sound like you want need an activator. You aren't trying to enforce value changes happen according to these rules, you are trying to make sure a module performs some logic before it is used. It only needs to perform this logic once, as it is a singleton.
Unfortunately RequireJS does not provide a way (that I know of) to wait for a module to perform async work.
Here is one thing you could do. Since Durandal's app.start
initialization is an asynchronous process, you could hook into it so that your call to setRoot
comes after global
has initialized.
define(['durandal/app', 'plugins/ajax', 'durandal/global'], function (app,ajax) {
return function GlobalModule() {
activate: function() {
return //some promise;
}
};
});
define(['durandal/system', 'durandal/app', 'durandal/global'],
function (system, app, global) {
app.configurePlugins({ /* plugins */ });
app.title = 'App';
app.start()
.then(global.activate)
.then(function () {
app.setRoot('shell');
});
});
This will ensure that setRoot
doesn't start until global
has finished activating. It should then be safe in any of your app code to use it.
Please keep in mind I have no idea what durandal/global
is, and this work depends on activate
being a promise returning function.