Deactivate from within an activate view model?

180 views
Skip to first unread message

Nick Joseph

unread,
Sep 16, 2013, 6:08:14 PM9/16/13
to duran...@googlegroups.com
Is there a prescribed way to allow an activated viewmodel to signal to its activator that it should be closed/deactivated?

So far I've thought about having a "shouldClose" observable on the child viewmodel that the parent viewmodel can subscribe to and trigger deactivation that way.  But that seems too contrived.
I also thought about raising an Event from the child viewmodel and have the parent viewmodel listen for that event.
I even thought about using Durandal's Pub/Sub mechanism to notify the parent viewmodel that the child should close.  But that seemed like overkill.

Before I went any further I wanted to check if there's already a way to accomplish what I want.

Here's some basic code to illustrate what I'm trying to do:

Workspace.js
define([
'durandal/activator',
'./SomeModule'
], function (
activator,
SomeModule
) {
var Workspace = function () {
this.child = activator.create();
};
Workspace.prototype = {
showChild: function () {
var vm = new SomeModule();
this.child.activateItem(vm);
},
hideChild: function () {
 /* I need this method to be triggered by the child view model (don't I?) */
this.child.deactivate(true);
}
};
return Workspace;
});

Workspace.html
<div>
<button data-bind="click: showChild">Show Child</button>
<div data-bind="if: child()">
<div data-bind="compose: child"></div>
</div>
</div>

SomeModule.js
define([
'knockout'
], function (
ko
) {
var SomeModule = function () {

};
SomeModule.prototype = {
canDeactivate: function() {
/* pretend there's logic here */
return true;
},
close: function () {
/* how to notify the controlling activator to deactivate/close? */
}
};
return SomeModule;
});

SomeModule.html
<div>
<button data-bind="click: close">Close</button>
</div>

Any guidance is greatly appreciated.

Jonathan Curtis

unread,
Sep 17, 2013, 4:29:04 AM9/17/13
to duran...@googlegroups.com
The easiest way is to pass the parent to the child:

var vm = new SomeModule(this);

var SomeModule = function (parent) {
    this.parent = parent;
};

close: function () {
    this.parent.hideChild();
}

The only downside is that the modules are now coupled, which, in this case, is probably not a problem. If it is, use events.

Nick Joseph

unread,
Sep 17, 2013, 10:24:31 AM9/17/13
to duran...@googlegroups.com
Thanks for the reply.  Looking at it now, I was just making things harder than they needed to be.

I can't have the coupling in this particular scenario, so I went ahead and used the 'durandal/events' module to raise a "close" event.

fpw...@gmail.com

unread,
Oct 25, 2013, 11:06:14 AM10/25/13
to duran...@googlegroups.com
Hi Nick,

Instead of passing an object to the child you could pass a function, this would remove the coupling.  You can use the same pattern that Jonathan suggested but instead of passing in the parent and calling the hide function on the parent, you just pass the hide function and call it directly:

var vm = new SomeModule(parent.hideChild);

var SomeModule = function (closeMeCallBack) {
    this.closeMe = function() {
        //check to make sure something was passed in
        if(closeMeCallBack)
        {
            closeMeCallBack();
        }
    };
};

this way somemodule does not know anything about the parent, it just knows that when I need to close, I just call this function with no parameters.
Reply all
Reply to author
Forward
0 new messages