Backbone.Component plugin adds component concept to Backbone. If you are familiar with web components draft or components in Ember, the idea of Backbone.Component is very similar.
You can think of component as of isolated view-like object controlling some typical UI elements.
Backbone.Component is an open-source part of http://sourcetalk.net
Say you have a date picker element controlled by some jQuery plugin. It is used in some of your views, so every time you render a view you need to initialize your date pickers, and probably also deinitialize on exit. Thus you need to write a lot of duplicate code.
In the general case you can't solve this issue with inheritance, since you may need to use the same plugin in the views having different parents, while you don't want to execute that code in every single view.
Creating a subview for that element is a bit better, but you still have to manually handle all these subviews.
That's what Backbone.Component is for.
Backbone.Component is available in Bower repository as backbone_component. If you use Bower, execute the following in your terminal window:
bower install backbone_componentOtherwise, just copy the file you need (minified or development version) to your javascript directory.
You need to include backbone-component.js in your project after backbone.js.
The only external dependencies of Backbone.Component are Backbone itself and Underscore (which is also required by Backbone). jQuery/Zepto is not required, but as in case of Backbone gives you additional posiibilities (see below).
Also, Backbone.Comonent depends on MutationObserver. If you want to support browsers that don't implement it (e.g. IE<11) you need to use some polyfill.
First, you need to initialize Backbone.Component (the values below are the defaults):
Backbone.Component.initialize(
{
"namespace" : Backbone.Components ,
"baseViewClass" : Backbone.View ,
"transformHTML" : null
}
);-
namespace- namespace containing your components. If for any reason you don't use namespaces at all and store all your classes in global namespace, you can set"namespace" : window, and that will work, but you better don't do this. This option accepts array of namespaces in case you have several namespaces for your components. -
baseViewClass- base class for your views. UsuallyBackbone.View, but you may use your own parent class. Please keep in mind that the prototype of the view passed here will be extended, so if you don't want to add method to your base class you can create a separate base class to use with components (but in this case they won't be available anywhere else). -
transformHTML- wrapper for the generated HTML, a function accepting and returning a string. This may be helpful if your template engine escapes HTML by default but allows an option to unescape it (safemethod inSkim), or you want to add your custom HTML to that generated byBackbone.Component. If set tonull(by default), doesn't perform any transformation.
You need to extend Backbone.Component and override 3 methods:
Backbone.Components.YourComponent = Backbone.Component.extend(
{
generate: function( your, own, params ) { } ,
activate: function( ) { } ,
deactivate: function( ) { }
}
);-
generate- generates base HTML of your component. Most probably it will contain some template processing code. In the simplest case, you can even pointgenerateto a template processing method:generate: _.template( "<div>...</div>" ). It must return the string containing the generated HTML. In this method, you can define any arguments you need. It is supposed that the last argument is a hash containing additional options, but you can safely ignore this convention. Currently 2 options have the impact on the generated HTML:options.wrapper.htmlIdandoptions.wrapper.htmlClass, they will appropriately setidandclassof the wrapper HTML element. Also you are free to add your own options for your components. -
activate- any code you need to activate your component. This method is called when the component appears in DOM. It is executed for every single component instance in your view. In case of our hypothetical date picker plugin, it can look like this:this.$( "input" ).datepicker( ). Accepts no arguments, any returned value is ignored. -
deactivate- any code you need to safely deactivate your component. This method is called when the component disappears from DOM. It is executed for every single component instance in your view. In many cases, it isn't really necessary, and you can skip this method. Accepts no arguments, any returned value is ignored.
Once you defined your component class, you can render your component in templates by calling insertYourComponent method. Assuming you use underscore-like templates, and inside the template this points to your Backbone.View instance, you render your components like this:
<%= this.insertYourComponent( your, own, params ) %>All the arguments here are passed to the component's generate method unchanged. insert<ComponentName> methods are added to your base view class during Backbone.Component initialization.
In some cases you may preffer writing HTML for your components manually instead of generating it in your component class. You can still take advantage of using Backbone.Component's activate & deactivate methods. In this case you need to call observeYourComponent somewhere in your view's render method. Just like insert methods, observe methods are added to your base view class during initialization. They accept a single argument: CSS selector of your component.
this.observeYourComponent( ".your-component-class" );Now everytime an element with the given selector appears/disappears, component's activate/deactivate method executes.
Though not a descendant of Backbone.View, Backbone.Component inherits some of its methods and variables. Here they are: el, $el, events, $( ), setElement( ), delegateEvents( )/undelegateEvents( ) (most probably you'll never need to explicitly call these two). All these methods and variables work in exactly the same way as they do in Backbone.View.
Also, Backbone.Component uses Backbone.Event mixin, so you are free to use events in your components just like in any other Backbone object.
Note: some of these methods and variables are available only if you use jQuery or similar lib. See Backbone documentation for more details.
If you are familiar with Ruby on Rails or similar MVC framework, you probably already know what helpers are. In Backbone.Component, helpers are very similar to components except that they don't have activation/deactivation logic.
To create a component, you need to extend Backbone.Helper and override generate method. In the simplest case, your helper may look like this:
Backbone.Helpers.YourHelper = Backbone.Helper.extend(
{
generate: _.template( "<div>...</div>" );
}
);Or you may need to perform some complex operations and place this code in generate method instead of template itself.
Now you can call it in your templates:
<%= this.insertYourHelper( your, own, params ) %>Unlike components, helpers do not inherit Backbone.View's methods and variables, and do not use Backbone.Events.
Note: for performance reasons, you should not use components where helpers will do the work. Backbone.Component doesn't observe helpers in the way it observes components, so if all you need is to render a template, please consider using helpers.
- Allow multi-element selectors in
observemethods reobserveAllremoved, reobserving now happens automatically- Various minor updates and fixes
- Initial version