Angular — Introduction to ngNewRouter vs ui-router
Introduction to the new router planned for AngularJS 1.5+/2.0 including nested routes.
Update 31/5/15: Angular 1.4 was released this week and the new router was not part of it. Now it’s planned to be in Angular 1.5.
I am going to skip the theory blurb and show you two implementations side-by-side (ui-router vs ngNewRouter) so you can figure the differences out by looking at the code. Hope I don’t lose you. Use the links below to see it running.
Demo code for ui-router | Demo code for ngNewRouter
Follow me on Twitter for latest updates @gerardsans.
If you are using ngRoute, you can read the same article but using ngRoute instead of ui-router here.
Let’s dive right into it to get a better feel of the changes.
Warning: be aware changes are expected prior official 1.5 release.
Setting up routes
Let’s imagine we have a basic website with two sections: home and users. The users section shows a list and uses a nested view to display users details when clicking on a user.
Using ui-router we would do:
First I included ui.router to the app followed by the home and users components. During the config phase I setup the routes by using $urlRouteProvider (default route) and $stateProvider for the rest. As this is happening during AngularJS configuration phase you need to know the routes ahead of time.
We defined home and users states mapping to corresponding routes, templates and controllers. For the nested route we defined the state users.details and passed and id that would correspond to routes like ‘#/users/43’.
Let’s see how you would do the same with ngNewRouter.
Here you can see how I moved the router logic into the AppController component; to setup the routes I used $router instead, this time we are out of the configuration phase, so its being applied dynamically. See also how the resulting syntax is much cleaner than before. We are using redirectTo to redirect to the /home route as we did before.
This magic can be done by using some conventions so Angular can figure out the old controller, controllerAs and the templateUrl.
For the nested route we will use the following setup within the UserController in the users component. This will map ‘#/users/:id’ routes to the details component.
Placeholder
Before with ui-router we were using ui-view on our index.html like this
So when the user navigates to /home, angular will instantiate the HomeController using the controllerAs as home and then it will render the home.tpl.html template inside the ui-view placeholder.
With ngNewRouter you will use the ng-viewport directive instead.
Here we use AppController, where we defined our routes. The convention for ng-viewport is that it will be equal to ‘default’ when omitted. So the previous code would be equal to ng-viewport=”default”.
For more complex scenarios you can use multiple ng-viewport instances rendering different content like this
<div ng-viewport="master"></div>
<div ng-viewport="detail"></div>
Links
With ui-router you can translate the links at the top with ui-sref
<a href=”#/home”>Home</a>
<a href=”#/user/5”>Batman</a><a ui-sref="home">Home</a>
<a ui-sref="users.details({id:5})">Batman</a>
In ngNewRouter you use the new ng-link directive.
<a ng-link="home">Home</a>
<a ng-link="users({id:5})">Batman</a>
For the last bit of the previous example the setup for the route would be
// during Angular Config
$router.config([
{ path: '/users/:id', component: 'users' },
...
]);// statically
Controller.$routeConfig = [
{ path: 'users/:id', component: 'users' }
];
New Route Components
As we have seen before, with ui-router all routes were defined using $stateProvider during the configuration phase so when a new route was triggered angular could use the registered controller, controllerAs and templateUrl.
Now with ngNewRouter this changes slightly so instead of mapping states to routes we are mapping routes to components. By doing this, we get the same features as before but now dynamically. The default conventions for a home component would be HomeController, using controllerAs home, and the templateUrl being placed in ‘components/home/home.html’.
If you want to use a different setup you can do so by using the $componentLoaderProvider. For example, to change the template convention to be like /home.tpl.html you would do
angular
.module('myapp')
.config(function ($componentLoaderProvider) {
$componentLoaderProvider.setTemplateMapping(function (name) {
// name is component name
return name + ‘.tpl.html’;
});
})
That’s all for the introduction. Hope you enjoyed it!
If you want to go deeper I recommend you the fantastic links below. Thanks for reading! Have any questions? Ping me on Twitter @gerardsans.
More Resources
A 10 minute primer to the new Angular router, Preview of the New Angular Router (Official AngularJS blog), angular/router (GitHub)