Important
You are browsing the documentation for version 4.2 of OroCommerce, OroCRM and OroPlatform, which is no longer maintained. Read version 5.1 (the latest LTS version) of the Oro documentation to get up-to-date information.
See our Release Process documentation for more information on the currently supported and upcoming releases.
Page Component¶
Page Component is an invisible component that takes responsibility of the controller for certain functionality. It accepts options object, performs initialization actions, and, at appropriate time, destroys initialized elements (views, models, collections, or even sub-components).
Definition¶
To define PageComponent for a block define several data-attributes for the HTML node:
data-page-component-module with the name of the module
data-page-component-options with safe JSON-string
data-page-component-name optional, allows to get access to the component by name
{% set options = {
metadata: metaData,
data: data
} %}
<div data-page-component-module="mybundle/js/app/components/grid-component"
data-page-component-options="{{ options|json_encode }}"></div>
Hint
See also Component Shortcuts
How It Works¶
PageController loads a page, triggering ‘page:update’ event. Global views (PageRegionView) have updated their contents. And once it is done — each PageRegionView executes initLayout method for it’s layout element (in common case it’s the view element). Inside this method, the view excutes ‘layout:init’ handler, that initializes system UI-controls (such as ScrollSpy, ToolTips, PopOvers and other), after that invokes initPageComponents method, that initializes components defined in HTML. This method:
collects all elements with proper data-attributes.
loads defined modules of PageComponents.
initializes PageComponents, executing init method with passed-in options.
returns promise object, allowing handle initialization process.
PageController handles promises from all global views and once they all resolved — triggers next event ‘page:afterChange’.
Development¶
There are two kinds of PageComponents:
an extension of BaseComponent.
just a function for trivial cases.
Extending BaseComponent¶
BaseComponent is a module oroui/js/app/components/base/component very similar to Backbone.View. The difference is that it is not visible and has no functionality to interact with DOM.
It has two static methods:
extend, the same as other Backbone components have.
init, that accepts options and creates an instance of the current component. If the component instance has no defer property (meaning tha component has been created synchronously) init method returns this component. If it has defer property, init method returns a promise object. Once the component get initialized, it should resolve defer with its instance.
An instance of BaseComponent has several methods:
initialize, that accepts options and performs initialization;
dispose, that besides removing all kind of event subscriptions like all Chaplin components do goes though subComponents property (that is an array), disposes all its sub-components, and then tries to call dispose method for all other properties;
delegateListeners, implements support of listeners declaration over listen property (see Chaplin.View documentation)
delegateListener, adds listener for a corresponded target: ‘model’, ‘collection’, ‘mediator’ or itself (if no target passed);
_deferredInit, create flag of deferred initialization
_resolveDeferredInit, resolves deferred initialization and executes promise’s handlers
MyComponent = BaseComponent.extend({
initialize: function (options) {
options = options || {};
this.processOptions(options);
if (!_.isEmpty(options.modules)) {
// deferred init start, means myView will be initialized in async way
this._deferredInit();
// there are some modules we need to load before init view
loadModules(options.modules, function (modules) {
_.extend(options.viewOptions, modules);
this.initView(options.viewOptions);
// resolves deferred initialization once view gets ready
self._resolveDeferredInit();
}, this);
} else {
// initialize view immediately
this.initView(options);
}
},
processOptions: function (options) {
/* manipulate options, merge them with defaults, etc. */
},
initView: function (options) {
this.view = new MyView(options);
}
});
Function as a Component¶
For some trivial cases writing the entire component as extension from BaseComponent is redundant. This is definitely the case if you don’t need to:
dispose this component (the result is self-disposable), or
extend the component for other cases.
In this case it’s better to define a function that accepts options and performs the initialization:
define(['jquery', 'js/my-widget'], function ($) {
return function (options) {
$(options.el).myWidget(options.widgetOptions);
};
}