Dovetail Agent Behaviors
As Views become more and more complex, the View becomes less about displaying model data, and more about interactions. These interactions tend to be chunks of logic that need to be used in multiple views.
In Dovetail Agent and Dovetail SelfService, Marionette Behaviors are used to apply this logic to view elements.
What is a Behavior?
In the Dovetail applications, there are behaviors that apply code to elements and patterns that are repeated frequently.
One of the best examples in Dovetail Agent is the Date Picker. The Date Picker behavior sets up a date picker control for each element that contains a ‘date-picker’ class. The value of the picker is synced to the view’s model with the attribute being the same name as the id of the picker.
What that means is that for any input field in a form on a view that is used for date entry, a calendar control will be displayed, and the value selected will be stored in the view model for getting it back to the server.
The big benefit of behaviors is separating reusable code from the views. With Date Pickers, any view with one or more date input elements will use the standard calendar controls just by declaring the Date Picker behavior to be used within the view.
Defining a New Behavior
Behaviors extend the Marionette Behavior class. Any events that are triggered by the view’s triggerMethod function are passed to each Behavior on the view as well. That makes it easy to build a behavior that interacts with a view’s elements. As an example, adding a behavior to populate a select control via Ajax when a view is rendered becomes pretty simple.
When a view gets rendered, the onRender event gets triggered. Setting up the behavior to act on this event is the perfect place to add options to the select controls. Here is the behavior definition and its event handler:
When the onRender event happens, each select element on the view with a class of ‘data-list’ will get updated with options built from its list, found in its data property.
var DataLists = Marionette.Behavior.extend({ onRender: function () { var self = this; var dataLists = this.$('select.data-list'); dataLists.each(function() { var listName = $(this).data('list'); if(listName !== '') { self.setUpDataListOptions($(this), listName); } }); }, setUpDataListOptions: function ($select, listName) { $.ajax({ url: app.root + 'get_list', type: "GET", dataType: "json", data: { list: listName }, success: function (options) { _.each(options, function (o) { var o = $('<option>' + o.text + '</option>').attr('value', o.value); $select.append(o); }); } }); } });
Declaring the New Behavior
In Dovetail Agent and SelfService, the Behaviors that are defined are all registered in behaviors.js. This file defines the location for where the Behaviors are stored, so the each view does not have to include the behaviors it needs.
For the example above, its definition would be:
adding the path to the behavior:
‘app/behaviors/dataLists’
and adding the declaration:
window.Behaviors.DataLists = DataLists;
Using the New Behavior
In any view that has a select element for selection of states, adding this code will get the options added when the control is rendered:
behaviors: { DataLists: {} }
That’s all that the view needs in order to trigger the behavior, since the behavior is defined to act on the onRender event.
Summary
Behaviors are a great way to reduce code complexity and duplication. They are easy to define and implement. When multiple views need the same logic applied to them, it is a great time to extract that code into a behavior.