There are three aspects to the component API: component and mixin definition, component instantiation, and base component methods. The base component methods are available as first-class citizens from within component and mixins definitions.
Components are AMD modules and should return a defined component. This is an example component file:
// AMD module definition define(function () { // require defineComponent var defineComponent = require('flight/lib/component'); // export defined component return defineComponent(myComponent); // component definition function myComponent () { // internal methods this.foo = function () { // do something }; }; });
Mixins are AMD modules exactly like components, only they return a component definition, rather than a defined component, so don't require defineComponent
:
// AMD module definition define(function () { return myMixin; // mixin definition function myMixin () { // internal methods this.bar = function () { // do something }; }; });
Mixins can be mixed into components, as shown in the following code:
// AMD module definition define(function () { // require defineComponent var defineComponent = require('flight/lib/component'); // require mixins var myMixin = require('component/my_mixin'); // export defined component, adding mixins return defineComponent(myComponent, myMixin); // component definition function myComponent () { // internal methods this.foo = function () { // components have access to mixin methods // as first-class citizens this.bar(); }; }; });
Mixins can also be mixed into other mixins using compose.mixin
within the mixin definition. For example, look at the following code:
// AMD module definition define(function () { // require Compose var compose = require('flight/lib/compose'); // require another mixin var someOtherMixin = require('component/some_other_mixin'); return myMixin; // mixin definition function myMixin () { compose.mixin(this, [someOtherMixin]); // internal methods this.bar = function () { // do something }; }; });
The following code example shows a component (component/my_component.js
) being required and then instantiated in three different ways:
// require component constructor var MyComponent = require('component/my_component'); // attach component instance to an HTMLElement MyComponent.attachTo(document); // attach component instance to all elements matching a css selector MyComponent.attachTo('.modal'); // attach component instance to a jQuery object var $div = $('<div />'); MyComponent.attachTo($div); // pass options to component instance MyComponent.attachTo($div, { defaultText: 'Hello, World!' });
The defineComponent
method mixes in Flight's core functionality into a component definition. The methods in this section are available to any component within the function definition.
Component methods can be broken up into five sections: Advice, Attributes, DOM selection, Events, and Teardown.
Advice allows component and mixin methods to be extended or overridden without clobbering the original method using before
, after
, and around
. Advice is also used to initialize a component.
Default attributes can be used to configure a component or mixin:
// component definition function myComponent () { this.defaultAttrs({ defaultText: "Hello, handsome!" }); });
Default attributes can be overridden when instantiating a component:
var MyComponent = require('component/my_component'); MyComponent.attachTo(document, { defaultText: "Hello, World!" });
Use a selector defined in defaultAttrs
to gain a reference to a jQuery collection containing elements within the component that match the selector:
this.defaultAttrs({ listItemSelector: '.list-item' }); this.getListItems = function () { var $listItems = this.select(attrKey); return $listItems; };
Flight components should attach event listeners and trigger events through Flight's event methods:
Attach an event listener to the component root:
this.on([selector], eventName, callback);
In the this
example, an event listener is attached to the component's root node:
this.handleTaskData = function (event, data) { // do something }; this.after('initialize', function () { this.on('dataTask', this.handleTaskData); });
To attach an event listener to a specific element, a CSS selector, DOM element, or jQuery collection can be passed as the first argument to on
, as seen in the following examples:
this.on('.list-item', 'click', this.handleListItemClick); this.on($('.list-item'), 'click', this.handleListItemClick); this.on(document, 'dataTask', this.handleTaskData);
To handle dynamic creation of elements, use the following syntax to provide event delegation. attributeKey
needs to be defined in defaultAttrs
.
this.on(eventName, { attributeKey: callback });
In this example, handleListItemClick
will be called when the user clicks on an element matching .list-item
.
this.defaultAttrs({ listItemSelector: '.list-item' }); this.handleListItemClick = function (event) { // do something }); this.after('initialize', function () { this.on('click' { listItemSelector: this.handleListItemClick }); });
this.off([selector, ] eventName [, callback]);
In this example, all listeners listening for dataTask
events will be removed.
this.off('dataTask');