Extension 

Kind: global interface


Extensions provide means of extending the page controllers with additional managed state and logic. An extension has access to the current route parameters, can specify the resources to load when the page is loading or being updated, may intercept event bus events and modify the state of the page just like an ordinary controller, except that the modifications are restricted to the state fields which the extension explicitly specifies using its getAllowedStateKeys() method.

Why use extensions

Best case to use extension is a component that requires interception of controller lifecycle events and/or loading external data.

Putting the component’s logic inside the controller would be unwise for 3 reasons:

  1. Controller would contain code that is not as clear. For new-commers to your project it’d seem strange why you’re mixing e.g. HomeController logic with GalleryComponent logic.
  2. Component file and its extension file should be kept together because nothing is bigger pain than searching for related code in the whole project structure.
  3. Component can be used in multiple Views. That means you’d have to copy & paste the same logic to multiple controllers.

How to use extensions

As mentioned above, the extension file should be next to a file of the component it’s extending. For example:

app/
  ├─ ...
  ├─ component
  |   ├─ ...
  |   └─ gallery
  |   |   ├─ Gallery.jsx
  |   |   ├─ gallery.less
  |   |   └─ GalleryExtension.js
  |   └─ ...
  └─ ...

In the extension file should be plain class extending ima/extension/AbstractExtension with the same methods as you’d use in the controller. In addition you should implement getAllowedStateKeys() method which returns array of keys the extension is allowed to change in controller’s state.

Note: List and description of controller methods can be seen in Controller lifecycle.

// app/component/gallery/GalleryExtension.js
import AbstractExtension from 'ima/extension/AbstractExtension';

export default class GalleryExtension extends AbstractExtension {

  load() {
    // Where the magic happens...
  }
}

All extensions to be used on a page must be added to the current controller via addExtension() method before the controller is initialized (Good place for that is the init() method). After that, the extensions will go through the same lifecycle as the controller.

Note: Controller and extension methods are called in a series but the controller methods are called first.

import AbstractController from 'ima/controller/AbstractController';
import GalleryExtension from 'app/component/gallery/GalleryExtension';

export default class PostController extends AbstractController {
  
  init() {
    this.addExtension(GalleryExtension);
  }
}


extension.init() 

Callback for initializing the controller extension after the route parameters have been set on this extension.

Kind: instance method of Extension


extension.destroy() 

Finalization callback, called when the controller is being discarded by the application. This usually happens when the user navigates to a different URL.

This method is the lifecycle counterpart of the init method.

The extension should release all resources obtained in the init method. The extension must release any resources that might not be released automatically when the extensions’s instance is destroyed by the garbage collector.

Kind: instance method of Extension


extension.activate() 

Callback for activating the extension in the UI. This is the last method invoked during controller (and extensions) initialization, called after all the promises returned from the load method have been resolved and the controller has configured the meta manager.

The extension may register any React and DOM event listeners in this method. The extension may start receiving event bus event after this method completes.

Kind: instance method of Extension


extension.deactivate() 

Callback for deactivating the extension in the UI. This is the first method invoked during extension deinitialization. This usually happens when the user navigates to a different URL.

This method is the lifecycle counterpart of the activate method.

The extension should deregister listeners registered and release all resources obtained in the activate method.

Kind: instance method of Extension


extension.load() ⇒ Object.<string, (Promise\|\*)> 

Callback the extension uses to request the resources it needs to render its related parts of the view. This method is invoked after the init method.

The extension should request all resources it needs in this method, and represent each resource request as a promise that will resolve once the resource is ready for use (these can be data fetched over HTTP(S), database connections, etc).

The method must return a plain flat object. The field names of the object identify the resources being fetched and prepared, each value must be either the resource (e.g. view configuration or a value retrieved synchronously) or a Promise that will resolve to the resource.

The IMA will use the object to set the state of the controller.

Any returned promise that gets rejected will redirect the application to the error page. The error page that will be used depends on the status code of the error.

Kind: instance method of Extension
Returns: Object.<string, (Promise\|\*)> - A map object of promises resolved when all resources the extension requires are ready. The resolved values will be pushed to the controller’s state.


extension.update([prevParams]) ⇒ Object.<string, (Promise\|\*)> 

Callback for updating the extension after a route update. This method is invoked if the current route has the onlyUpdate flag set to true and the current controller and view match those used by the previously active route, or, the onlyUpdate option of the current route is a callback and returned true.

The method must return an object with the same semantics as the result of the load method. The controller’s state will then be patched by the returned object.

The other extension lifecycle callbacks (init, load, activate, deactivate, Extension#deinit) are not call in case this method is used.

Kind: instance method of Extension
Returns: Object.<string, (Promise\|\*)> - A map object of promises resolved when all resources the extension requires are ready. The resolved values will be pushed to the controller’s state.

Param Type Default Description
[prevParams] Object.<string, string> {} Previous route parameters.

extension.setState(statePatch) 

Patches the state of the controller using this extension by using the provided object by copying the provided patch object fields to the controller’s state object.

Note that the state is not patched recursively but by replacing the values of the top-level fields of the state object.

Note that the extension may modify only the fields of the state that it has specified by its getAllowedStateKeys method.

Kind: instance method of Extension

Param Type Description
statePatch Object.<string, \*> Patch of the controller’s state to apply.

extension.getState() ⇒ Object.<string, \*> 

Returns the current state of the controller using this extension.

Kind: instance method of Extension
Returns: Object.<string, \*> - The current state of the controller.


extension.setPartialState(partialStatePatch) 

Patches the partial state of the extension. The extension is able during its load and update phase receive state from active controller using this extension and from previously loaded/updated extensions.

Kind: instance method of Extension

Param Type Description
partialStatePatch Object.<string, \*> Patch of the controller’s state to apply.

extension.getPartialState() ⇒ Object.<string, \*> 

Returns the current partial state of the extension.

Kind: instance method of Extension
Returns: Object.<string, \*> - The current partial state of the extension.


extension.clearPartialState() 

Clears the current partial state of the extension and sets it value to empty object.

Kind: instance method of Extension


extension.setPageStateManager(pageStateManager) 

Sets the state manager used to manage the controller’s state..

Kind: instance method of Extension

Param Type Description
pageStateManager PageStateManager The current state manager to use.

extension.switchToStateManager() 

Enables using PageStateManager for getting state.

Kind: instance method of Extension


extension.switchToPartialState() 

Disables using PageStateManager for getting state.

Kind: instance method of Extension


extension.setRouteParams([params]) 

Sets the current route parameters. This method is invoked before the init method.

Kind: instance method of Extension

Param Type Default Description
[params] Object.<string, string> {} The current route parameters.

extension.getRouteParams() ⇒ Object.<string, string> 

Returns the current route parameters.

Kind: instance method of Extension
Returns: Object.<string, string> - The current route parameters.


extension.getAllowedStateKeys() ⇒ Array.<string> 

Returns the names of the state fields that may be manipulated by this extension. Manipulations of other fields of the state will be ignored.

Kind: instance method of Extension
Returns: Array.<string> - The names of the state fields that may be manipulated by this extension.