-
Notifications
You must be signed in to change notification settings - Fork 3
Routing
Routing is an essential part of every application that displays multiple pages. It allows to develop each part of an application separately and add new parts instantly. As it happens to be in MVC frameworks, each route targets specific controller which takes control over what happens next after a route is matched.
All routes in IMA.js are registered inside the init
function in app/config/routes.js
. Same init
function can be found in app/config/bind.js
. See Object Container documentation for more information about the oc.get()
function.
import RouteNames from 'ima/router/RouteNames';
import HomeController from 'app/page/home/HomeController';
import HomeView from 'app/page/home/HomeView';
// ...
export let init = (ns, oc, config) => {
const router = oc.get('$Router');
router
.add('home', '/', HomeController, HomeView)
.add(RouteNames.ERROR, '/error', ErrorController, ErrorView)
.add(RouteNames.NOT_FOUND, '/not-found', NotFoundController, NotFoundView);
}
First argument passed to the add()
method is unique route name. You will use this name when you'll be creating a link.
Second argument is a path to be matched. Inside the URL you can use parameter substituions. Parameter name can contain only letters a-zA-Z
, numbers 0-9
, underscores _
and hyphens -
and is preceeded by colon :
.
router.add('order-detail', '/user/:userId/orders/:orderId', OrderController, OrderView);
The userId
and orderId
parameters are then accessible in OrderController
via this.params
.
// app/page/order/OrderController.js
import AbstractController from 'ima/controller/AbstractController';
class OrderController extends AbstractController {
// ... Probably construct() with userService and orderSerivce dependencies
load() {
let userPromise = this._userService.getUser(this.params.userId);
let orderPromise = this._orderService.getOrder(this.params.orderId);
return {
user: userPromise,
order: orderPromise
}
}
}
Parameters can also be marked as optional by placing question mark ?
after the colon :
.
Note: Optional parameters can be placed only after the last slash. Doing otherwise can cause unexpected behavior.
router.add('user-detail', '/profile/:?userId', UserController, UserView);
Next 2 parameters are controller and view class. When a route is matched the assigned Controller goes through its full lifecycle and renders the View.
The last parameter are options for the route.
{
onlyUpdate: false,
autoScroll: true,
allowSPA: true,
documentView: null,
managedRootView: null,
viewAdapter: null
}
-
onlyUpdate
{boolean | Function} - When only the parameters of the current route change anupdate
method of the active controller will be invoked instead of re-instantiating the controller and view. Theupdate
method receivesprevParams
object containing - as the name suggests - previous route parameters. If you provide function to theonlyUpdate
option; it receives 2 arguments (instances of previous controller and view) and it should return boolean. -
autoScroll
{boolean} - Flag that signals whether the page should be scrolled to the top when the navigation occurs. -
allowSPA
{boolean} - This flag can be used to make the route be always served from the server and never using the SPA even if the server is overloaded. This is useful for routes that use different document views (specified by thedocumentView
option), for example for rendering the content of iframes. -
documentView
{?AbstractDocumentView} -
managedRootView
{?function(new: React.Component)} -
viewAdapter
{?function(new: React.Component)}
Creating links is done via the link()
method on Router. Inside the Views and Components you can use helper function this.link()
inherited from ima/page/AbstractComponent
or ima/page/AbstractPureComponent
.
Note: Under the hood,
this.link()
is only alias forthis.utils.$Router.link()
.
render() {
const { user, order } = this.props;
const orderLink = this.link('order-detail', {
userId: user.id,
orderId: order.id
});
return <a href={orderLink}>View order</a>
}
Linking in Controllers requires a few more steps but still is manageble. First you import Router via dependencies.
Note: For more info about Dependency Injection see Object Container.
import AbstractController from 'ima/controller/AbstractController';
export default class DetailController extends AbstractController {
static get $dependencies() {
return [
'$Router'
];
}
constructor(router) {
this._router = router;
}
Then you're free to use this._router.link()
method as you wish.
- Introduction
- Static view
- Adding some state
- Fetching the data from the server
- Writing posts
- Final polish