The Marionette views use an event lifecycle, triggering events on any listeners to act at different points inside the creation and destruction of views and their children.
View
Lifecycle
CollectionView
Lifecycle
NextCollectionView
Lifecycle
Region
s and the View Lifecycle
View
LifecycleMarionette views define a number of events during the creation and destruction
lifecycle - when the view is displayed in and emptied from a region. In the
documentation, we will reference the event name, though
onEvent
handling can be used.
All automatically fired events pass the triggering view to all event handlers as the first argument.
When a view is initialized and then displayed inside a region (using
showChildView()
) a set of events will be called in a specific order.
Order | Event | Arguments |
---|---|---|
1 | before:render |
view - view being rendered |
2 | render |
view - view being rendered |
3* | before:attach |
view - view being attached |
4* | attach |
view - view being attached |
5* | dom:refresh |
view - view being rendered |
The events marked with "*" only fire if/when the region's el
is attached to the DOM.
When region.empty()
is called, the view will be destroyed, calling events as
part of the destruction lifecycle.
Order | Event | Arguments |
---|---|---|
1 | before:destroy |
view - view being destroyed |
...args - arguments passed to destroy |
||
2* | before:detach |
view - view being detached |
3* | dom:remove |
view - view being detached |
4* | detach |
view - view being detached |
5 | destroy |
view - view being destroyed |
...args - arguments passed to destroy |
The events marked with "*" only fire if/when the view was attached to the DOM.
The order of the destruction events is dependent on when the view (or a parent view) is detached. When a parent attached view is destroyed it will receive the events as listed above, but its children will receive both detach events first when the parent is detached and the children will be destroyed after the detach is complete.
Order | Event | Arguments |
---|---|---|
1 | before:detach |
view - view being detached |
2* | dom:remove |
view - view being detached |
3* | detach |
view - view being detached |
4* | before:destroy |
view - view being destroyed |
...args - arguments passed to destroy |
||
5 | destroy |
view - view being destroyed |
...args - arguments passed to destroy |
The events marked with "*" only fire if/when the view was attached to the DOM.
These events are fired during the view's creation and rendering in a region.
before:render
Triggered before a View is rendered.
var Mn = require('backbone.marionette');
Mn.View.extend({
onBeforeRender: function() {
// set up final bits just before rendering the view's `el`
}
});
render
This is the optimal event for handling child views.
Triggered after the view has been rendered.
You can implement this in your view to provide custom code for dealing
with the view's el
after it has been rendered.
var Mn = require('backbone.marionette');
Mn.View.extend({
onRender: function() {
console.log('el exists but is not visible in the DOM');
}
});
before:attach
Triggered after the View has been rendered but just before it is first bound
into the page DOM. This will only be triggered once per region.show()
. If
you are re-rendering your view after it has been shown, you most likely want to
listen to the render
or dom:refresh
events.
attach
This is the optimal event to handle when the view's el
must be in the DOM.
Clean up any added handlers in before:detach
.
Triggered once the View has been bound into the DOM. This is only triggered
once - the first time the View is attached to the DOM. If you are re-rendering
your view after it has been shown, you most likely want to listen to the
dom:refresh
event.
dom:refresh
This is the optimal event to handle when the view's contents must be in the DOM.
Clean up any added handlers in dom:remove
.
The dom:refresh
event is fired in two separate places:
attach
event)render
method is calledconst myView = new Mn.View({
template: _.template('<span><%= count %><span>'),
templateContext: function() {
this.count = (this.count || 0) + 1;
return {
count: this.count
};
},
onRender: function() {
console.log('render');
},
onAttach: function() {
console.log('attach');
},
onDomRefresh: function() {
console.log('dom:refresh');
}
});
// some layout view
layout.showChildView('myRegion', myView);
/*
Output:
render
attach
dom:refresh
*/
myView.render();
/*
Output:
render
dom:refresh
*/
These events are fired during the view's destruction and removal from a region.
before:destroy
Triggered just prior to destroying the view, when the view's destroy()
method has been called.
The view may or may not be in the DOM at this point.
var Mn = require('backbone.marionette');
Mn.View.extend({
onBeforeDestroy: function() {
// custom destroying and non-DOM related cleanup goes here
}
});
before:detach
This is the optimal event for cleaning up anything added in onAttach
.
The View
will trigger the before:detach
event when the view is rendered and
is about to be removed from the DOM.
If the view has not been attached to the DOM, this event will not be fired.
var Mn = require('backbone.marionette');
Mn.View.extend({
onBeforeDetach: function() {
// custom destroying and DOM related cleanup goes here
}
});
detach
The View
will trigger the detach
event when the view was rendered and has
just been removed from the DOM.
dom:remove
This is the optimal event for cleaning up anything added in onDomRefresh
.
The dom:remove
event is fired in two separate places:
before:detach
event)render
method is called if the view is already rendered.const myView = new Mn.View({
template: _.template('<span><%= count %><span>'),
templateContext: function() {
this.count = (this.count || 0) + 1;
return {
count: this.count
};
},
onBeforeRender: function() {
console.log('before:render');
},
onRender: function() {
console.log('render');
},
onBeforeDetach: function() {
console.log('before:detach');
},
onDetach: function() {
console.log('detach');
},
onDomRemove: function() {
console.log('dom:remove');
}
});
// some layout view
layout.showChildView('myRegion', myView);
myView.render();
/*
Output:
before:render
dom:remove
render
*/
myView.destroy();
/*
Output:
before:detach
dom:remove
detach
*/
destroy
Triggered just after the view has been destroyed. At this point, the view has been completely removed from the DOM.
These events are fired on specific actions performed on the view.
before:add:region
When you add a region to a view - through addRegion()
- the
before:add:region
event will fire just before the region is actually added.
add:region
When a region is added to a view - through addRegion()
- the add:region
event will be fired. This happens just after the region is added and is
available to use on the view.
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
onAddRegion: function(name, region) {
console.log('Region called ' + name + ' was added');
}
});
var myView = new MyView();
myView.addRegion('regionName', '#selector');
before:remove:region
The View
will trigger a before:remove:region
event before a region is removed from the view.
This allows you to perform any cleanup operations before the region is removed.
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
onBeforeRemoveRegion: function(name) {
console.log('Region called ' + name + ' is about to be removed');
},
regions: {
regionName: '#selector'
}
});
var myView = new MyView();
myView.removeRegion('foo');
remove:region
The View
will trigger a remove:region
event when a region is removed from the view.
This allows you to use the region instance one last
time, or remove the region from an object that has a
reference to it:
var Mn = require('backbone.marionette');
var view = new Mn.View();
view.on('remove:region', function(name, region) {
// add the region instance to an object
delete myObject[name];
});
view.addRegion('foo', '#bar');
view.removeRegion('foo');
CollectionView
LifecycleThe CollectionView
has its own lifecycle around the standard View
event
rendering lifecycle. This section covers the events that get triggered and what
they indicate.
The CollectionView
creation lifecycle can go down two paths depending on
whether the collection is populated or empty. The below table shows the order of
rendering events firing:
Order | Event | Arguments |
---|---|---|
1 | before:render |
collectionview - collection view being rendered |
2* | before:render:empty |
collectionview - collection view being rendered |
view - empty view being rendered |
||
2+ | before:render:children |
collectionview - collection view being rendered |
3 | before:add:child |
collectionview - collection view being rendered |
child - child view being rendered |
||
4 | add:child |
collectionview - collection view being rendered |
child - child view being rendered |
||
5* | render:empty |
collectionview - collection view being rendered |
view - empty view being rendered |
||
5+ | render:children |
collectionview - collection view being rendered |
6 | render |
collectionview - collection view being rendered |
7 | before:attach |
collectionview - collection view being rendered |
8 | attach |
collectionview - collection view being rendered |
9 | dom:refresh |
collectionview - collection view being rendered |
The events marked with "*" only fire on empty collections and events marked with "+" fire on collections with items.
When a CollectionView
is destroyed it fires a series of events in order to
reflect the different stages of the destruction process.
Order | Event | Arguments |
---|---|---|
1 | before:destroy |
collectionview - collection view being destroyed |
...args - arguments passed to destroy |
||
2 | before:detach |
collectionview - collection view being destroyed |
3 | detach |
collectionview - collection view being destroyed |
4 | before:destroy:children |
collectionview - collection view being destroyed |
5* | before:remove:empty |
collectionview - collection view being destroyed |
5+ | before:remove:child |
collectionview - collection view being destroyed |
view - child view being destroyed |
||
6* | remove:child |
collectionview - collection view being destroyed |
view - child view being destroyed |
||
6+ | remove:empty |
collectionview - collection view being destroyed |
7 | destroy |
collectionview - collection view being destroyed |
...args - arguments passed to destroy |
The events marked with "*" only fire on empty collections and events marked with "+" fire on collections with items.
before:render
Triggers before the CollectionView
render process starts. See the
before:render
Documentation for an
example.
before:render:empty
Triggers just before rendering a collection emptyView
. This won't be fired if
the collection has 1 or more elements in.
before:render:children
This event fires just before rendering the children in the CollectionView
.
This only fires if the collection has at least one item.
before:add:child
This event fires before each child is added to the view. If the collection is
empty, this fires exactly once for the emptyView
.
add:child
This event fires after each child is added to the view. This fires once for each item in the attached collection.
If the collection is empty, this event fires exactly once for the emptyView
.
render:empty
This event fires once the emptyView
has been rendered. This will only fire if
the attached collection is empty.
render:children
This event fires once all the collection's child views have been rendered. This
only fires if the collection has at least one item. This may also fire when
reorderOnSort
is false:
var Bb = require('backbone');
var Mn = require('backbone.marionette');
var MyView = Mn.CollectionView.extend({
onRenderChildren: function({
console.log('The collectionview children have been rendered');
})
});
var myView = new MyView({
collection: new Bb.Collection([{ id: 1 }]);
});
myView.render();
render
Fires when the collection has completely finished rendering. See the
render
Documentation for more information.
before:destroy
Fires as the destruction process is beginning. This is best used to perform any
necessary cleanup within the CollectionView
.
var Mn = require('backbone.marionette');
var MyView = Mn.CollectionView.extend({
onBeforeDestroy: function() {
console.log('The CollectionView is about to be destroyed');
}
});
var myView = new MyView();
myView.destroy();
before:detach
Fires just before the CollectionView
is removed from the DOM. If you need to
remove any event handlers or UI modifications, this would be the best time to do
that.
detach
Fires just after the CollectionView
is removed from the DOM. The view's
elements will still exist in memory if you need to access them.
before:destroy:children
This is triggered just before the childView
items are destroyed.
Triggered when the collectionView
is destroyed or before the collectionView
's children are re-rendered.
before:remove:empty
This is triggered just before the emptyView
is removed from the
CollectionView
. This only fires if the attached collection
has no items.
The emptyView
will then go through the its own
destruction lifecycle
before:remove:child
This is triggered for each childView
that is removed from the
CollectionView
. This can only fire if the collection
contains items.
Each item in the CollectionView
will undergo the
destruction lifecycle
remove:empty
Fired after the emptyView
has been removed and its destruction lifecycle has
been completed. This only fires if the attached collection
has no items.
remove:child
Fired for each view that is removed from the CollectionView
. This can only
fire if the collection
has items.
destroy
Fired once the CollectionView
has been destroyed and no longer exists.
Collection views can fire other events as part of their normal use.
reorder
/ before:reorder
eventsWhen reorderOnSort
is set to true
, these
events are fired for the reordering of the collection.
var Bb = require('backbone');
var Mn = require('backbone.marionette');
var MyView = Mn.CollectionView.extend({...});
var myCol = new Bb.Collection({ comparator: ... })
var myView = new MyView({ reorderOnSort: true });
myView.render();
myCol.comparator = function () { return this.get('foo'); };
myView.on({
'reorder': function() {
console.log('the collection view has been reordered following its collection');
},
'before:reorder': function() {
console.log('the collection view is about to be reordered');
}
});
myCol.sort()
NextCollectionView
LifecycleThe NextCollectionView
has its own lifecycle around the standard View
event
rendering lifecycle. This section covers the events that get triggered and what
they indicate.
The NextCollectionView
creation lifecycle can go down two paths depending on
whether the collection is populated or empty. The below table shows the order of
rendering events firing:
Order | Event | Arguments |
---|---|---|
1* | before:render |
collectionview - collection view being rendered |
2 | before:remove:child |
collectionview - collection view being rendered |
child - child view being rendered |
||
3 | remove:child |
collectionview - collection view being rendered |
child - child view being rendered |
||
4 | before:add:child |
collectionview - collection view being rendered |
child - child view being rendered |
||
5 | add:child |
collectionview - collection view being rendered |
child - child view being rendered |
||
view - empty view being rendered |
||
6+ | before:sort |
collectionview - collection view being rendered |
7 | sort |
collectionview - collection view being rendered |
8# | before:filter |
collectionview - collection view being rendered |
9# | filter |
collectionview - collection view being rendered |
10 | before:render:children |
collectionview - collection view being rendered |
11 | render:children |
collectionview - collection view being rendered |
12* | render |
collectionview - collection view being rendered |
13** | before:attach |
collectionview - collection view being rendered |
14** | attach |
collectionview - collection view being rendered |
15** | dom:refresh |
collectionview - collection view being rendered |
"*" only fire if the NextCollectionView
is fully rendering from either collectionView.render()
or collectionView.collection.reset()
.
"+" including and after this point only occur if there are some children to render.
"#" only fires if a viewFilter
is defined.
"**" fires from use in the parent when a CollectionView is shown in a Region or
as a childView of another CollectionView.
When a NextCollectionView
is destroyed it fires a series of events in order to
reflect the different stages of the destruction process.
Order | Event | Arguments |
---|---|---|
1 | before:destroy |
collectionview - collection view being destroyed |
...args - arguments passed to destroy |
||
2 | before:detach |
collectionview - collection view being destroyed |
3 | detach |
collectionview - collection view being destroyed |
4 | before:destroy:children |
collectionview - collection view being destroyed |
5+ | before:remove:child |
collectionview - collection view being destroyed |
view - child view being destroyed |
||
6+ | remove:child |
collectionview - collection view being destroyed |
view - child view being destroyed |
||
7 | destroy:children |
collectionview - collection view being destroyed |
8 | destroy |
collectionview - collection view being destroyed |
...args - arguments passed to destroy |
The events marked with "+" only fire on collections with children.
before:render
Triggers before the NextCollectionView
render process starts. See the
before:render
Documentation for an
example.
before:add:child
This event fires before each child is added to the children.
add:child
This event fires after each child is added to the children. This fires once for each item in the attached collection.
before:sort
This event fires just before sorting the children in the NextCollectionView
.
By default this only fires if the collectionView has at least one child.
sort
This event fires after sorting the children in the NextCollectionView
.
By default this only fires if the collectionView has at least one child.
before:filter
This event fires just before filtering the children in the NextCollectionView
.
By default this only fires if the collectionView has at least one child and has a viewFilter
.
filter
This event fires after filtering the children in the NextCollectionView
.
By default this only fires if the collectionView has at least one child and has a viewFilter
.
before:render:children
This event fires just before rendering the children in the NextCollectionView
.
By default this only fires if the collectionView has at least one view not filtered out.
render:children
This event fires once all the collection's child views have been rendered. By default this only fires if the collectionView has at least one view not filtered out.
var Bb = require('backbone');
var Mn = require('backbone.marionette');
var MyView = Mn.NextCollectionView.extend({
onRenderChildren: function({
console.log('The collectionview children have been rendered');
})
});
var myView = new MyView({
collection: new Bb.Collection([{ id: 1 }]);
});
myView.render();
render
Fires when the collection has completely finished rendering. See the
render
Documentation for more information.
before:destroy
Fires as the destruction process is beginning. This is best used to perform any
necessary cleanup within the NextCollectionView
.
var Mn = require('backbone.marionette');
var MyView = Mn.NextCollectionView.extend({
onBeforeDestroy: function() {
console.log('The CollectionView is about to be destroyed');
}
});
var myView = new MyView();
myView.destroy();
before:detach
Fires just before the NextCollectionView
is removed from the DOM. If you need to
remove any event handlers or UI modifications, this would be the best time to do
that.
detach
Fires just after the NextCollectionView
is removed from the DOM. The view's
elements will still exist in memory if you need to access them.
before:destroy:children
This is triggered just before the childView
items are destroyed.
Triggered when the NextCollectionView
is destroyed or before the NextCollectionView
's children are re-rendered.
before:remove:child
This is triggered for each childView
that is removed from the
NextCollectionView
. This can only fire if the collection
contains items.
Each item in the NextCollectionView
will undergo the
destruction lifecycle
remove:child
Fired for each view that is removed from the NextCollectionView
. This can only
fire if the collection
has items.
destroy:children
This is triggered just after the childView
items are destroyed.
Triggered when the NextCollectionView
is destroyed or before the NextCollectionView
's children are re-rendered.
destroy
Fired once the NextCollectionView
has been destroyed and no longer exists.
The NextCollectionView
uses a region internally that can be used to know when the empty view is show or destroyed.
var Mn = require('backbone.marionette');
var MyView = Mn.NextCollectionView.extend({
emptyView: MyEmptyView
});
var myView = new MyView();
myView.emptyRegion.on({
show: function() {
console.log('CollectionView is empty!');
},
empty: function() {
console.log('CollectionView is removing the emptyView');
}
});
myView.render();
Both View
and CollectionView
share methods for checking if the view is attached or rendered.
isRendered()
This function will return a boolean value reflecting if the view has been rendered.
isAttached()
This function will return a boolean value reflecting if the view believes it is attached.
This is maintained when attaching a view with a Region
or during View instantiation.
If a view is attached by other means this function may not reflect the actual state of attachment.
To be certain use Marionette.isNodeAttached
.
When a view is instantiated, if the View's el
is set to an existing node
the view's isRendered()
will return true
and before:render
and render
events will not be fired when the view is shown in a Region.
Similarly if the el
is attached to a node in the DOM the view's isAttached()
will return true
and before:attach
, attach
and dom:refresh
will not be fired
when the view is shown in a Region.
Region
s and the View LifecycleWhen 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.
When showing a view inside a region, the region emits a number of events:
Order | Event | Arguments |
---|---|---|
1 | before:show |
region - region showing the child view |
view - view being shown in the region |
||
options - options passed to show() |
||
2 | View Creation Lifecycle | |
3 | show |
region - region showing the child view |
view - view being shown in the region |
||
options - options passed to show() |
before:show
Emitted on region.show(view)
, before the view lifecycle begins. At this point,
none of the view rendering will have been performed.
show
Emitted after the view has been rendered and attached to the DOM (if this region is already attached to the DOM). This can be used to handle any extra manipulation that needs to occur.
When emptying a region, it will emit destruction events around the view's destruction lifecycle:
Order | Event | Arguments |
---|---|---|
1 | before:empty |
region - region being emptied |
view - view being removed |
||
2 | View Destruction Lifecycle | |
3 | empty |
region - region being emptied |
view - view being removed |
before:empty
Emitted before the view's destruction process begins. This can occur either by
calling region.empty()
or by running region.show(view)
on a region that's
displaying another view. It will also trigger if the view in the region is
destroyed.
empty
Fired after the entire destruction process is complete. At this point, the view has been removed from the DOM completely.
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.
const NonMonitoredView = Mn.View.extend({
monitorViewEvents: false
});
Important 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.