On this page
Class Events
Marionette uses triggerMethod
internally to trigger various events used within the classes. This provides 'onEvent' binding providing convenient hooks for handling class events. Notably all internally triggered events will pass the triggering class instance as the first argument of the event.
Documentation Index
- Application Events
- Behavior Events
- Region Events
- MnObject Events
- View Events
- CollectionView Events
- DOM Change Events
- Destroy Events
- Supporting Backbone Views
Application Events
The Application
object will fire two events:
before:start
event
Fired just before the application is started. Use this to prepare the application with anything it will need to start, for example instantiating routers, models, and collections.
start
event
Fired as part of the application startup. This is where you should be showing your views and starting Backbone.history
.
import Bb from 'backbone';
import { Application } from 'backbone.marionette';
import MyModel from './mymodel';
import MyView from './myview';
const MyApp = Application.extend({
region: '#root-element',
initialize(options) {
console.log('Initialize' + options.foo);
},
onBeforeStart(app, options) {
this.model = new MyModel(options.data);
},
onStart(app, options) {
this.showView(new MyView({model: this.model}));
Bb.history.start();
}
});
const myApp = new MyApp({ foo: 'My App' });
myApp.start({ data: { bar: true } });
As shown the options
object is passed into the Application
as the second argument to start
.
Application destroy
events
The Application
class also triggers Destroy Events.
Behavior Events
initialize
event
After the view and behavior are constructed and initialized, the last event to occur is an initialize
event on the behavior which is passed the view instance and any options passed to the view at instantiation.
import { Behavior, View } from 'backbone.marionette';
const MyBehavior = Behavior.extend({
onInitialize(view, options) {
console.log(options.msg);
}
});
const MyView = View.extend({
behaviors: [MyBehavior]
});
const myView = new MyView({ msg: 'view initialized' });
Note This event is unique in that the triggering class instance (the view) is not the same instance as the handler (the behavior). In most cases internally triggered events are triggered and handled by the same instance, but this is an exception.
Proxied Events
A Behavior
's view events are proxied directly on the behavior.
Note In order to prevent conflict Behavior
does not trigger destroy events with its own destruction. A destroy
event occurring on the Behavior
will have originated from the related view.
Region Events
When you show a view inside a region - either using region.show(view)
or showChildView('region', view)
- the Region
will emit events around the view events that you can hook into.
The Region
class also triggers Destroy Events.
show
and before:show
events
These events fire before (before:show
) and after (show
) showing anything in a region. A view may or may not be rendered during before:show
, but a view will be rendered by show
.
The show
events will receive the region instance, the view being shown, and any options passed to region.show
.
import { Region, View } from 'backbone.marionette';
const MyRegion = Region.extend({
onBeforeShow(myRegion, view, options) {
console.log(myRegion.hasView()); //false
console.log(view.isRendered()); // false
console.log(options.foo === 'bar'); // true
},
onShow(myRegion, view, options) {
console.log(myRegion.hasView()); //true
console.log(view.isRendered()); // true
console.log(options.foo === 'bar'); // true
}
});
const MyView = View.extend({
template: _.template('hello')
});
const myRegion = new MyRegion({ el: '#dom-hook' });
myRegion.show(new MyView(), { foo: 'bar' });
empty
and before:empty
events
These events fire before (before:empty
) and after (empty
) emptying a region's view. These events will not fire if there is no view in the region, even if the region detaches DOM from within the region's el
. The view will not be detached or destroyed during before:empty
, but will be detached or destroyed during the empty
.
The empty events will receive the region instance, the view leaving the region.
import { Region, View } from 'backbone.marionette';
const MyRegion = Region.extend({
onBeforeEmpty(myRegion, view) {
console.log(myRegion.hasView()); //true
console.log(view.isDestroyed()); // false
},
onEmpty(myRegion, view) {
console.log(myRegion.hasView()); //false
console.log(view.isDestroyed()); // true
}
});
const MyView = View.extend({
template: _.template('hello')
});
const myRegion = new MyRegion({ el: '#dom-hook' });
myRegion.empty(); // no events, no view emptied
myRegion.show(new MyView());
myRegion.empty();
MnObject Events
The MnObject
class triggers Destroy Events.
View Events
add:region
and before:add:region
events
These events fire before (before:add:region
) and after (add:region
) a region is added to a view. This event handler will receive the view instance, the region name string, and the region instance as event arguments. The region is fully instantated for both events.
remove:region
and before:remove:region
events
These events fire before (before:remove:region
) and after (remove:region
) a region is removed from a view. This event handler will receive the view instance, the region name string, and the region instance as event arguments. The region will be not be destroyed in the before event, but is destroyed by remove:region
.
Note Currently these events are only triggered using the view.removeRegion
API and not when the region is destroyed directly. https://github.com/marionettejs/backbone.marionette/issues/3602
CollectionView Events
The CollectionView
triggers unique events specifically related to child management.
add:child
and before:add:child
events
These events fire before (before:add:child
) and after (add:child
) each child view is instantiated and added to the children
. These will fire once for each item in the attached collection or for any view added using addChildView
.
remove:child
and before:remove:child
events
These events fire before (before:remove:child
) and after (remove:child
) each child view is removed to the children
. A view may be removed from the children
if it is destroyed, if it is removed from the collection
or if it is removed with removeChildView
.
NOTE A childview may or may not be destroyed by this point.
NOTE When a CollectionView
is destroyed it will not individually remove its children
. Each childview will be destroyed, but any needed clean up during the CollectionView
's destruction should happen in before:destroy:children
.
sort
and before:sort
events
These events fire before (before:sort
) and after (sort
) sorting the children in the CollectionView
. These events will only fire if there are children
and a viewComparator
filter
and before:filter
events
These events fire before (before:filter
) and after (filter
) filtering the children in the CollectionView
. This event will only fire if there are children
and a viewFilter
.
When the filter
event is fired the children filtered out will have already been detached from the view's el
, but new children will not yet have been rendered. The filter
event not only receives the view instance, but also arrays of attached views, and detached views.
const MyCollectionView = CollectionView.extend({
onBeforeFilter(myCollectionView) {
console.log('Nothing has changed yet!');
},
onFilter(myCollectionView, attachViews, detachedView) {
console.log('Array of attached views', attachedView);
console.log('Array of detached views', attachedView);
}
});
render:children
and before:render:children
events
Similar to Region
show
and before:show
events these events fire before (before:render:children
) and after (render:children
) the children
of the CollectionView
are attached to the CollectionView
's el
or childViewContainer
.
These events will be passed the CollectionView
instance and the array of views being attached. The views in the array may or may not be rendered or attached for before:render:children
, but will be rendered and attached by render:children
.
If the CollectionView
can determine that added views will only be appended to the end, only the appended views will be passed to the event. Otherwise all of the children
views will be passed.
Note if you consistently need all of the views within this event use children
destroy:children
and before:destroy:children
events
These events fire before (before:destroy:children
) and after (destroy:children
) destroying the children in the CollectionView
. These events will only fire if there are children
.
CollectionView EmptyView Region Events
The CollectionView
uses a region internally that can be used to know when the empty view is show or destroyed. See Region Events.
import { CollectionView } from 'backbone.marionette';
const MyView = CollectionView.extend({
emptyView: MyEmptyView
});
const myView = new MyView();
myView.getEmptyRegion().on({
'show'() {
console.log('CollectionView is empty!');
},
'before:empty'() {
if (this.hasView()) {
console.log('CollectionView is removing the emptyView');
}
}
});
myView.render();
DOM Change Events
render
and before:render
events
Reflects when a view's template is being rendered into its el
.
before:render
will occur prior to removing any current child views. render
is an ideal event for attaching child views to the view's template as the first render generally occurs prior to the view attaching to the DOM.
import { View, CollectionView } from 'backbone.marionette';
import MyChildView from './MyChildView';
const MyView = View.extend({
template: _.template('<div class="foo-region"></div>'),
regions: {
'foo': '.foo-region'
},
onRender() {
this.showChildView('foo', new MyChildView());
}
});
const MyCollectionView = CollectionView.extend({
childView: MyChildView,
onRender() {
// Add a child not from the `collection`
this.addChildView(new MyChildView());
}
})
Note This event is only triggered when rendering a template into a view. A view that is pre-rendered will not have this event triggered unless re-rendered. Pre-rendered views should use initialize
for attaching child views and the render
event if the view is re-rendered.
Note If a view's template
is set to false
this event will not trigger.
attach
and before:attach
events
Relects when the el
of a view is attached to the DOM. These events will not trigger when a view is re-rendered as the el
itself does not change.
attach
is the ideal event to setup any external DOM listeners such as jQuery
plugins that use the view's el
, but not its contents.
detach
and before:detach
events
Relects when the el
of a view is detached from the DOM. These events will not trigger when a view is re-rendered as the el
itself does not change.
before:detach
is the ideal event to clean up any external DOM listeners such as jQuery
plugins that use the view's el
, but not its contents.
dom:refresh
event
Relects when the contents of a view's el
change in the DOM. This event will fire when the view is first attach
ed. It will also fire if an attached view is re-rendered.
This is the ideal event to setup any external DOM listeners such as jQuery
plugins that use DOM within the el
of the view and not the view's el
itself.
NOTE This event will not fire if the view has no template to render unless it contains prerendered html.
dom:remove
event
Relects when the contents of a view's el
are about to change in the DOM. This event will fire when the view is about to be detach
ed. It will also fire before an attached view is re-rendered.
This is the ideal event to clean up any external DOM listeners such as jQuery
plugins that use DOM within the el
of the view and not the view's el
itself.
NOTE This event will not fire if the view has no template to render unless it contains prerendered html.
Advanced Event Settings
Marionette is able to trigger attach
/detach
events down the view tree along with triggering the dom:refresh
/dom:remove
events because of the view event monitor. This monitor starts when a view is created or shown in a region (to handle non-Marionette views).
In some cases it may be a useful performance improvement to disable this functionality. Doing so is as easy as setting monitorViewEvents: false
on the view class.
import { View } from 'backbone.marionette';
const NonMonitoredView = View.extend({
monitorViewEvents: false
});
Note: Disabling the view monitor will break the monitor generated events for this view and all child views of this view. Disabling should be done carefully.
Destroy Events
destroy
and before:destroy
events
Every class has a destroy
method which can be used to clean up the instance. With the exception of Behavior
's each of these methods triggers a before:destroy
and a destroy
event.
As a general rule, onBeforeDestroy
is the best handler for cleanup as the instance and any internally created children are already destroyed by the time onDestroy
is called.
Note For views this is not the ideal location for clean up of anything touching the DOM. See dom:remove
or [before:detach
] for DOM related clean up.
import { Application, View } from 'backbone.marionette';
const MyView = View.extend({
onBeforeDestroy(options) {
console.log(options.foo);
}
});
const myView = new MyView();
mvView.destroy({ foo: 'destroy view' });
const MyApp = Application.extend({
onBeforeDestroy(options) {
console.log(options.foo);
}
});
const myApp = new MyApp();
myApp.destroy({ foo: 'destroy app' });
CollectionView
destroy:children
and before:destroy:children
events
Similar to destroy
, CollectionView
has events for when all of its children are destroyed. See the CollectionView's events for more information.
Supporting Backbone Views
Marionette.Events
and triggerMethod
Internally Marionette uses triggerMethod
for event triggering. This API is not available to Backbone.View
s so in order to support Backbone.View
s in Marionette v4+, Marionette.Events
must be mixed into the non-Marionette view.
This can be done for an individual view definition:
import { Events } from 'backbone.marionette';
const MyBbView = Backbone.View.extend(Events);
or for all Backbone.View
s
_.extend(Backbone.View.prototype, Events);
Lifecycle Events
render
and destroy
To support non-Marionette Views, Marionette uses two flags to determine if it should trigger render
and destroy
events on the view. If a custom view throws it's own render
or destroy
events, the related flag should be set to true
to avoid Marionette duplicating these events.
// Add support for triggerMethod
import { Events } from 'backbone.marionette';
_.extend(Backbone.View.prototype, Events);
const MyCustomView = Backbone.View.extend({
supportsRenderLifecycle: true,
supportsDestroyLifecycle: true,
render() {
this.triggerMethod('before:render');
this.$el.html('render html');
// Since render is being triggered here set the
// supportsRenderLifecycle flag to true to avoid duplication
this.triggerMethod('render');
},
destroy() {
this.triggerMethod('before:destroy');
this.remove();
// Since destroy is being triggered here set the
// supportsDestroyLifecycle flag to true to avoid duplication
this.triggerMethod('destroy');
}
});
DOM Change Lifecycle Events
As mentioned in Advanced Event Settings some DOM events are triggers from the view event monitor that will handle DOM attachment related events down the view tree. Backbone View's won't have the functionality unless the monitor is added. This will include all DOM Change Events other than render.
You can add the view events monitor to any non-Marionette view:
import { monitorViewEvents, Events } from 'backbone.marionette';
// Add support for triggerMethod
_.extend(Backbone.View.prototype, Events);
const MyCustomView = Backbone.View.extend({
initialize() {
monitorViewEvents(this);
// Ideally this happens first prior to any rendering
// or attaching that might occur in the initialize
}
});
© 2017 Muted Solutions, LLC
Licensed under the MIT License.
https://marionettejs.com/docs/v4.0.0/events.class.html