The Marionette Event system provides a system for objects to communicate with each other in a uniform way. In Marionette, this typically involves objects (models, collections, and views) triggering events that other objects (typically views) listen to and act on.
This section will mostly deal with View events and the semantics and methods of responding to events.
This section will not cover events from models and collections. See the documentation for View.
The traditional event handling system in Backbone is also supported in Marionette. Marionette, however, provides an alternative event system using the triggerMethod
method on Marionette.Object
- the key difference between the two is that triggerMethod
triggers magically named event handlers on views. This section covers how triggerMethod
works and how listeners are set up to handle it.
triggerMethod
The triggerMethod
method fires the named event on the view - any listeners will then be triggered on the event. If there are no listeners, this call will still succeed. All arguments after the first argument will be passed to all event handlers.
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
callMethod: function(myString) {
console.log(myString + ' was passed');
}
});
var myView = new MyView();
/* See Backbone.listenTo */
myView.on('something:happened', myView.callMethod, myView);
/* Calls callMethod('foo'); */
myView.triggerMethod('something:happened', 'foo');
The triggerMethod
call comes from the trigger-method
mixin that is also part of Marionette.Object
and its subclasses like Marionette.Application
. This documentation also applies.
Marionette's event triggers work just like regular Backbone events - you can use view.on
and view.listenTo
to act on events:
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
initialize: function() {
this.on('event:happened', this.logCall);
},
logCall: function(myVal) {
console.log(myVal);
}
});
You can also use listenTo
as in Backbone:
var Mn = require('backbone.marionette');
var OtherView = Mn.View.extend({
initialize: function(someView) {
this.listenTo(someView, 'event:happened', this.logCall);
},
logCall: function(myVal) {
console.log(myVal);
}
});
var MyView = Mn.View.extend();
var myView = new MyView();
var otherView = new OtherView(myView);
As in Backbone, listenTo
will pass the object it is called on in as the context variable. These behave exactly as in Backbone, so using object.on
will require you to unhook any event handlers yourself to prevent memory leaks. Marionette, however, does provide extra helpers as part of the view lifecycle that bind and unbind event handlers for you. this is the core of onEvent
Binding.
onEvent
BindingThe major difference between Backbone.trigger
and View.triggerMethod
is that triggerMethod
can fire specially named events on the attached view. For instance, a view that has been rendered will fire view.triggerMethod('render')
and call onRender
- providing a handy way to add behavior to your views.
Determining what method an event will call is easy, we will outline this with an example using before:dom:refresh
though this also works with any custom events you want to fire:
:
characters - so before
, dom
, refresh
Before
, Dom
, Refresh
on
- on
, Before
, Dom
, Refresh
onBeforeDomRefresh
Using this process, before:dom:refresh
will call the onBeforeDomRefresh
method. Let's see it in action with a custom event:
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
onMyEvent: function(myVal) {
console.log(myVal);
}
});
var myView = new MyView();
myView.triggerMethod('my:event', 'someValue'); // Logs 'someValue'
As before, all arguments passed into triggerMethod
will make their way into the event handler. Using this method ensures there will be no unexpected memory leaks.
events
and triggers
Views can automatically bind DOM events to methods and View events with events
and triggers
respectively:
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
events: {
'click a': 'showModal'
},
triggers: {
'keyup input': 'data:entered'
},
showModal: function(event) {
console.log('Show the modal');
},
onDataEntered: function(view, event) {
console.log('Data was entered');
}
});
For more information, see the view documentation.
The View
and CollectionView
are able to monitor and act on events on any children they own. Any events fired on a view are automatically propagated to their direct parents as well. Let's see a quick example:
var Mn = require('backbone.marionette');
var Item = Mn.View.extend({
tagName: 'li',
triggers: {
'click a': 'select:item'
}
});
var Collection = Mn.CollectionView.extend({
tagName: 'ul',
childViewEvents: {
'select:item': 'itemSelected'
},
itemSelected: function(childView) {
console.log('item selected: ' + childView.model.id);
}
});
Events fired on a view bubble up to their direct parent views, calling any event methods using the childview:
prefix (more on that shortly) and any methods bound to the childViewEvents
attribute. This works for built-in events, custom events fired with triggerMethod
and bound events using triggers
.
Note: Automatic event bubbling can be disabled by setting childViewEventPrefix
to false
.
When using implicit listeners, the childview:*
event prefix is used which needs to be included as part of the handler:
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
triggers: {
click: 'click:view'
},
doSomething: function() {
this.triggerMethod('did:something');
}
});
var ParentView = Mn.View.extend({
regions: {
foo: '.foo-hook'
},
onRender: function() {
this.showChildView('foo', new MyView());
},
onChildviewClickView: function(childView) {
console.log('View clicked ' + childView);
},
onChildviewDidSomething: function(childView) {
console.log('Something was done to ' + childView);
}
})
The view
gets passed into the handlers as the first argument.
CollectionView
This works exactly the same way for the CollectionView
and its childView
:
var Mn = require('backbone.marionette');
var MyChild = Mn.View.extend({
triggers: {
click: 'click:child'
}
});
var MyList = Mn.CollectionView.extend({
onChildviewClickChild: function(childView) {
console.log('Childview ' + childView + ' was clicked');
}
});
Just like with the View
and its regions, the event handler will receive the view
that triggered the event as its first argument.
You can customize the event prefix for events that are forwarded through the view. To do this, set the childViewEventPrefix
on the view or collectionview. For more information on the childViewEventPrefix
see Event bubbling.
The default value for childViewEventPrefix
is childview
. Setting this property to false
will disable automatic event bubbling.
var Bb = require('backbone');
var Mn = require('backbone.marionette');
var myCollection = new Bb.Collection([{}]);
var CollectionView = Mn.CollectionView.extend({
childViewEventPrefix: 'some:prefix'
});
var collectionView = new CollectionView({
collection: myCollection
});
collectionView.on('some:prefix:render', function(){
// child view was rendered
});
collectionView.render();
The childViewEventPrefix
can be provided in the view definition or in the constructor function call, to get a view instance.
To call specific functions on event triggers, use the childViewEvents
attribute to map child events to methods on the parent view. This takes events fired on child views - without the childview:
prefix - and calls the method referenced or attached function.
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
triggers: {
click: 'view:clicked'
}
});
var ParentView = Mn.View.extend({
regions: {
foo: '.foo-hook'
},
childViewEvents: {
'view:clicked': 'displayMessage'
},
onRender: function() {
this.showChildView('foo', new MyView());
},
displayMessage: function(childView) {
console.log('Displaying message for ' + childView);
}
});
The childViewEvents
attribute can also attach functions directly to be event handlers:
var Mn = require('backbone.marionette');
var MyView = Mn.View.extend({
triggers: {
click: 'view:clicked'
}
});
var ParentView = Mn.View.extend({
regions: {
foo: '.foo-hook'
},
childViewEvents: {
'view:clicked': function(childView) {
console.log('Function called for ' + childView);
}
},
onRender: function() {
this.showChildView('foo', new MyView());
}
});
CollectionView
's childViewEvents
var Mn = require('backbone.marionette');
// childViewEvents can be specified as a hash...
var MyCollectionView = Mn.CollectionView.extend({
childViewEvents: {
// This callback will be called whenever a child is rendered or emits a `render` event
render: function() {
console.log('A child view has been rendered.');
}
}
});
A childViewTriggers
hash or method permits proxying of child view events without manually setting bindings. The values of the hash should be a string of the event to trigger on the parent.
childViewTriggers
is sugar on top of childViewEvents
much in the same way that View triggers
are sugar for View events
.
// The child view fires a custom event, `show:message`
var ChildView = Marionette.View.extend({
// Events hash defines local event handlers that in turn may call `triggerMethod`.
events: {
'click .button': 'onClickButton'
},
triggers: {
'submit form': 'submit:form'
},
onClickButton: function () {
// Both `trigger` and `triggerMethod` events will be caught by parent.
this.trigger('show:message', 'foo');
this.triggerMethod('show:message', 'bar');
}
});
// The parent uses childViewEvents to catch the child view's custom event
var ParentView = Marionette.CollectionView.extend({
childView: ChildView,
childViewTriggers: {
'show:message': 'child:show:message',
'submit:form': 'child:submit:form'
},
onChildShowMessage: function (message) {
console.log('A child view fired show:message with ' + message);
},
onChildSubmitForm: function (childView) {
console.log('A child view fired submit:form');
}
});
var GrantParentView = Marionette.View.extend({
regions: {
list: '.list'
},
onRender: function() {
this.showChildView('list', new ParentView({
collection: this.collection
}));
},
childViewEvents: {
'child:show:message': 'showMessage'
},
showMessage: function(childView) {
console.log('A child (' + childView + ') fired an event');
}
});
CollectionView
's childViewTriggers
var Mn = require('backbone.marionette');
// The child view fires a custom event, `show:message`
var ChildView = Mn.View.extend({
// Events hash defines local event handlers that in turn may call `triggerMethod`.
events: {
'click .button': 'onClickButton'
},
// Triggers hash converts DOM events directly to view events catchable on the parent.
// Note that `triggers` automatically pass the first argument as the child view.
triggers: {
'submit form': 'submit:form'
},
onClickButton: function () {
// Both `trigger` and `triggerMethod` events will be caught by parent.
this.trigger('show:message', 'foo');
this.triggerMethod('show:message', 'bar');
}
});
// The parent uses childViewEvents to catch the child view's custom event
var ParentView = Mn.CollectionView.extend({
childView: ChildView,
childViewTriggers: {
'show:message': 'child:show:message',
'submit:form': 'child:submit:form'
},
onChildShowMessage: function (message) {
console.log('A child view fired show:message with ' + message);
},
onChildSubmitForm: function (childView) {
console.log('A child view fired submit:form');
}
});
Marionette Views fire events during their creation and destruction lifecycle. For more information see the documentation covering the View
Lifecycle.
© 2017 Muted Solutions, LLC
Licensed under the MIT License.
https://marionettejs.com/docs/v3.2.0/events.html