I am currently using Marionette 2.4.1.
I have a parent layout view (A) that contains a region that a child layout view (B) will show onto. I have a onShow
method on view (B) which is properly called when view (B) is shown. However, I have a onEmpty
and onBeforeEmpty
on view (B) to expect them to be called when view (B) is hidden. These are called from view (A) where I have a function that will empty out the region that view (B) populates however I pass {preventDestroy: true}
on the empty call.
My issue is, I was/am expecting view (B) to pick up on that before:empty
or empty
triggers that are called when #empty
is called from view (A) however, view (B) does not pick up those triggers. Not even view (B) seems to pick up on those triggers either.
What is the expected situation here? When running through the Marionette source code, I can see the onBeforeEmpty
trigger being called as per my source code:
Marionette._triggerMethod = (function() {
// split the event name on the ":"
var splitter = /(^|:)(\w)/gi;
// take the event section ("section1:section2:section3")
// and turn it in to uppercase name
function getEventName(match, prefix, eventName) {
return eventName.toUpperCase();
}
return function(context, event, args) {
var noEventArg = arguments.length < 3;
if (noEventArg) {
args = event;
event = args[0];
}
// get the method name from the event name
var methodName = 'on' + event.replace(splitter, getEventName);
var method = context[methodName];
var result;
// call the onMethodName if it exists
if (_.isFunction(method)) {
// pass all args, except the event name
result = method.apply(context, noEventArg ? _.rest(args) : args);
}
// trigger the event, if a trigger method exists
if (_.isFunction(context.trigger)) {
if (noEventArg + args.length > 1) {
context.trigger.apply(context, noEventArg ? args : [event].concat(_.drop(args, 0)));
} else {
context.trigger(event);
}
}
return result;
};
})();
Here is where I suspect it to trigger the method onBeforeEmpty
:
// get the method name from the event name
var methodName = 'on' + event.replace(splitter, getEventName);
var method = context[methodName];
It seems like the context is view (A).
Mariontte's Region#Empty:
// Destroy the current view, if there is one. If there is no
// current view, it does nothing and returns immediately.
empty: function(options) {
var view = this.currentView;
var preventDestroy = Marionette._getValue(options, 'preventDestroy', this);
// If there is no view in the region
// we should not remove anything
if (!view) { return; }
view.off('destroy', this.empty, this);
this.triggerMethod('before:empty', view);
if (!preventDestroy) {
this._destroyView();
}
this.triggerMethod('empty', view);
// Remove region pointer to the currentView
delete this.currentView;
if (preventDestroy) {
this.$el.contents().detach();
}
return this;
},
So here this.triggerMethod('before:empty', view);
it seems like this
refers to view (A) and view
refers to view (B). Is this intended? I thought the method would be triggered on view (B)? However, I cannot seem to see the method being triggered on view (A) either.
This this
in this.triggerMethod('before:empty', view);
refers to your the region of your layout. You can see more region lifecycle events/methods here: http://marionettejs.com/docs/v2.4.3/marionette.region.html#events-raised-on-the-region-during-show
If you are looking for methods to use in your view, onDestroy
and onBeforeDestroy
are probably what you are looking for. Views are 'destroyed' and Regions are 'emptied'. http://marionettejs.com/docs/v2.4.3/marionette.view.html#view-onbeforedestroy