k.backbone.marionette
Version:
Make your Backbone.js apps dance!
276 lines (219 loc) • 6.73 kB
Markdown
## [View the new docs](http://marionettejs.com/docs/marionette.behavior.html)
# Marionette.Behavior
A `Behavior` is an isolated set of DOM / user interactions that can be mixed into any `View` or another `Behavior`. `Behaviors` allow you to blackbox `View` specific interactions into portable logical chunks, keeping your `views` simple and your code DRY.
## Documentation Index
* [Motivation](#the-motivation)
* [Using Behaviors](#using)
* [API](#api)
* [Event proxy](#the-event-proxy)
* [Triggers](#triggers)
* [Model Events](#model-events)
* [Collection Events](#model-events)
* [Grouped Behaviors](#grouped-behaviors)
* [$](#$)
* [$el and el](#$el-and-el)
* [Defaults](#defaults)
* [View](#view)
## The Motivation
As you build more and more complex views, you will find that your `view` becomes less about displaying model data, and more about interactions.
These interactions tend to be chunks of logic that you want to use in multiple views.
## Using
Here is an example of a simple `itemView`. Let's take a stab at simplifying it, and abstracting behaviors from it.
```js
var MyView = Marionette.ItemView.extend({
ui: {
"destroy": ".destroy-btn"
},
events: {
"click @ui.destroy": "warnBeforeDestroy"
},
warnBeforeDestroy: function() {
alert("you are destroying all your data is now gone!");
this.destroy();
},
onShow: function() {
this.ui.destroy.tooltip({
text: "what a nice mouse you have"
});
}
});
```
Interaction points, such as tooltips and warning messages, are generic concepts. There is no need to recode them within your views. They are prime for abstraction into a higher level non-coupled concept, which is exactly what Behaviors provide you with.
Here is the syntax for declaring which behaviors get used within a view.
The keys in the hash are passed to `getBehaviorClass` to lookup the correct `Behavior` class.
The options for each behavior are also passed to said Behavior during initialization. The options are then stored within each behavior under `options`.
```js
var MyView = Marionette.ItemView.extend({
ui: {
"destroy": ".destroy-btn"
},
behaviors: {
DestroyWarn: {
message: "you are destroying all your data is now gone!"
},
ToolTip: {
text: "what a nice mouse you have"
}
}
});
```
Now let's create the `DestroyWarn` behavior.
```js
var DestroyWarn = Marionette.Behavior.extend({
// you can set default options
// just like you can in your Backbone Models
// they will be overriden if you pass in an option with the same key
defaults: {
"message": "you are destroying!"
},
// behaviors have events that are bound to the views DOM
events: {
"click @ui.destroy": "warnBeforeDestroy"
},
warnBeforeDestroy: function() {
alert(this.options.message);
// every Behavior has a hook into the
// view that it is attached to
this.view.destroy();
}
});
```
And onto the `Tooltip` behavior.
```js
var ToolTip = Marionette.Behavior.extend({
ui: {
tooltip: '.tooltip'
},
onShow: function() {
this.ui.tooltip.tooltip({
text: this.options.text
});
}
});
```
Finally, the user must define a location for where their `behaviors` are stored.
A simple example of this would look like this:
```js
Marionette.Behaviors.behaviorsLookup = function() {
return window.Behaviors;
}
```
In this example you would then store your behaviors like this:
```js
window.Behaviors.ToolTip = ToolTip;
window.Behaviors.DestroyWarn = DestroyWarn;
```
Note than in addition to extending a `View` with `Behavior`, a `Behavior` can itself use other behaviors. The syntax is identical to that used for a `View`:
```js
var Modal = Marionette.Behavior.extend({
behaviors: {
DestroyWarn: {
message: "Whoa! You sure about this?"
}
}
});
```
Nested behaviors act as if they were direct behaviors of the parent behavior's view instance.
## API
### The Event Proxy
Behaviors are powered by an event proxy. What this means is that any events that are triggered by the view's `triggerMethod` function are passed to each Behavior on the view as well.
As a real world example, whenever in your `view` you would have `onShow`, your behavior can also have this `onShow` method defined. The same follows for `modelEvents` and `collectionEvents`. Think of your behavior as a receiver for all of the events on your view instance.
This concept also allows for a nice decoupled method to communicate to behaviors from your view instance.
You can just call from within your view `this.triggerMethod("SomeEvent", {some: "data"})`. then your `behavior` class would look like this:
```js
Marionette.Behavior.extend({
onSomeEvent: function(data) {
console.log("wow such data", data);
}
});
```
### Triggers
Any `triggers` you define on the `Behavior` will be triggered in response to the
appropriate event on the view.
```js
Marionette.Behavior.extend({
triggers: {
'click .label': 'click:label'
}
});
```
### Model Events
`modelEvents` will respond to the view's model events.
```js
Marionette.Behavior.extend({
modelEvents: {
"change:doge": "onDogeChange"
},
onDogeChange: function() {
// buy more doge...
}
});
```
### Collection Events
`collectionEvents` will respond to the view's collection events.
```js
Marionette.Behavior.extend({
collectionEvents: {
add: "onCollectionAdd"
},
onCollectionAdd: function() {
}
});
```
### Grouped Behaviors
Then `behaviors` key allows a behavior to group multiple behaviors together.
```js
Marionette.Behavior.extend({
behaviors: {
SomeBehavior: {}
}
});
```
### $
`$` is a direct proxy of the views `$` lookup method.
```js
Marionette.Behavior.extend({
onShow: function() {
this.$('.zerg')
}
});
```
### $el and el
`el` is a direct proxy of the view's `el`.
Similarly, `$el` is a direct proxy of the view's `el` cached as a jQuery selector.
```js
Marionette.Behavior.extend({
onShow: function() {
this.$el.fadeOut('slow')
}
});
```
### defaults
`defaults` can be a `hash` or `function` to define the default options for your behavior.
The default options will be overridden depending on what you set as the options per behavior (this works just like a `backbone.model`).
```js
Marionette.Behavior.extend({
defaults: function() {
return {
'deepSpace': 9
}
}
});
```
```js
Marionette.Behavior.extend({
defaults: {
'dominion': 'invasion',
'doge': 'amaze'
}
});
```
### view
The `view` is a reference to the view instance that the `behavior` is on.
```js
Marionette.Behavior.extend({
handleDestroyClick: function() {
this.view.destroy();
}
});
```