In addition to what Backbone provides the views, Marionette has additional API for DOM interactions available to all Marionette view classes.
Marionette's Views extend Backbone.View
and so have references to the view's el
, $el
, and this.$()
as well as defining an events
hash.
These methods provide ways for interacting with the view scoped to it's el
and all of the view's children. To restate events
and this.$()
will query the view's template and all of the children. Marionette's added interfaces attempt to scope interactions with only the view's template, leaving the children to handle themselves.
Views can bind custom events whenever users perform some interaction with the DOM. Using the view events
and triggers
handlers lets us either bind user input directly to an action or fire a generic trigger that may or may not be handled.
The events
and triggers
attributes bind DOM events to actions to perform on the view. They each take a DOM event key and a mapping to the handler.
We'll cover a simple example:
import { View } from 'backbone.marionette';
const MyView = View.extend({
events: {
'drop': 'onDrop',
'click .btn-show-modal': 'onShowModal',
'click @ui.save': 'onSave'
},
triggers: {
'click @ui.close': 'close'
},
ui: {
save: '.btn-save',
close: '.btn-cancel'
},
onShowModal() {
console.log('Show the modal');
},
onSave() {
console.log('Save the form');
},
onDrop() {
console.log('Handle a drop event anywhere in the element');
}
});
Event listeners are constructed by:
'<dom event> [dom node]': 'listener'
The dom event
can be a jQuery DOM event - such as click
- or another custom event, such as Bootstrap's show.bs.modal
.
The dom node
represents a jQuery selector or a ui
key prefixed by @.
. The dom node
is optional, and if omitted, the view's $el
will be used as the selector. For more information about the ui
object, and how it works, see the documentation on ui.
events
The view events
attribute binds DOM events to functions or methods on the view. The simplest form is to reference a method on the view:
import { View } from 'backbone.marionette';
const MyView = View.extend({
events: {
'click a': 'onShowModal'
},
onShowModal(event) {
console.log('Show the modal');
}
});
The DOM event gets passed in as the first argument, allowing you to see any information passed as part of the event.
When passing a method reference, the method must exist on the View.
The events
attribute can also directly bind functions:
import { View } from 'backbone.marionette';
const MyView = View.extend({
events: {
'click a'(event) {
console.log('Show the modal');
}
}
});
As when passing a string reference to a view method, the events
attribute passes in the event
as the argument to the function called.
Note Backbone events
are delegated to the view's el
. This means that events with a dom node selector will be handled for the view and any decendants. So if you attach a child with the same selector as the parent event handler, the parent will handle the event for both views.
triggers
The view triggers
attribute binds DOM events to Marionette events that can be responded to at the view or parent level. For more information on events, see the events documentation. This section will just cover how to bind these events to views.
import { View } from 'backbone.marionette';
const MyView = View.extend({
triggers: {
'click a': 'click:link'
},
onClickLink(view, event) {
console.log('Show the modal');
}
});
When the a
tag is clicked here, the link:click
event is fired. This event can be listened to using the onEvent
Binding technique discussed in the events documentation.
The major benefit of the triggers
attribute over events
is that triggered events can bubble up to any parent views. For a full explanation of bubbling events and listening to child events, see the event bubbling documentation..
triggers
Event ObjectEvent handlers will receive the triggering view as the first argument and the DOM Event object as the second followed by any extra parameters triggered by the event.
NOTE It is strongly recommended that View's handle their own DOM event objects. It should be considered a best practice to not utilize the DOM event in external listeners.
By default all trigger events are stopped with preventDefault
and stopPropagation
methods. This by nature artificially scopes event handling to the view's template preventing event handling of the same selectors in child views. However you can manually configurethe triggers using a hash instead of an event name. The example below triggers an event and prevents default browser behaviour using preventDefault
.
import { View } from 'backbone.marionette';
const MyView = View.extend({
triggers: {
'click a': {
event: 'link:clicked',
preventDefault: true, // this param is optional and will default to true
stopPropagation: false
}
}
});
The default behavior for calling preventDefault
can be changed with the feature flag triggersPreventDefault
, and stopPropagation
can be changed with the feature flag triggersStopPropagation
.
The View
provides a mechanism to name parts of your template to be used throughout the view with the ui
attribute. This provides a number of benefits:
ui
To define your ui
hash, just set an object of named jQuery selectors to the ui
attribute of your View:
import { View } from 'backbone.marionette';
const MyView = View.extend({
template: MyTemplate,
ui: {
save: '#save-button',
close: '.close-button'
}
});
Inside your view, the save
and close
references will point to the jQuery selectors #save-button
and .close-button
respectively found only in the rendered MyTemplate
.
To get the handles to your UI elements, use the getUI(ui)
method:
import { View } from 'backbone.marionette';
const MyView = View.extend({
template: MyTemplate,
ui: {
save: '#save-button',
close: '.close-button'
},
onFooEvent() {
const $saveButton = this.getUI('save');
$saveButton.addClass('disabled');
$saveButton.attr('disabled', 'disabled');
}
});
As $saveButton
here is a jQuery selector, you can call any jQuery methods on it, according to the jQuery documentation.
events
and triggers
The UI attribute is especially useful when setting handlers in the events
and triggers
objects - simply use the @ui.
prefix:
import { View } from 'backbone.marionette';
const MyView = View.extend({
template: MyTemplate,
ui: {
save: '#save-button',
close: '.close-button'
},
events: {
'click @ui.save': 'onSave'
},
triggers: {
'click @ui.close': 'close'
},
onSave() {
this.model.save();
}
});
In this example, when the user clicks on #save-button
, onSave
will be called. If the user clicks on .close-button
, then the event close:view
will be fired on MyView
.
By prefixing with @ui
, we can change the underlying template without having to hunt through our view for every place where that selector is referenced - just update the ui
object.
© 2017 Muted Solutions, LLC
Licensed under the MIT License.
https://marionettejs.com/docs/v4.0.0/dom.interactions.html