NgUpgrade with the Angular router and ui-router

- JavaScript Developer and Blogger
Published: Fri Feb 10 2017

In the following post I will show how to combine the Angular router with ui-router in an Ng-Upgrade application.

Victor Savkin has already written a great article about combining the new Angular router with the built-in angular 1.x router.

This article follows Victor's approach. The only difference is that I am using ui-router instead of the regular Angular 1.x router.

As I expected, switching to ui-router doesn't really change the overall approach much. Still, I think it's useful to show an example using ui-router, particularly since ui-router is so popular in the Angular 1.x community.


Many existing Angular 1 projects are looking to Ng-Upgrade to help with the transition to Angular 2+.

Ng-Upgrade serves as the bridge between Angular 1.x and Angular 2+. It's what allows code from both frameworks to coexist in the same application during the migration to Angular 2+.

Combining the new Angular router with a legacy Angular 1.x router can be a big help during this phase. In the following sections I will show how to configure both routers, and essentially create two parallel routing universes.

Angular Router

I won't get into details about how to configure Ng-Upgrade since there are already plenty of articles covering this. If you are new to Ng-Upgrade you might want to check out my other article about how to create optimized Ng-Upgrade application bundles using AoT and Tree Shaking.

The routing configuration follows the standard Angular router setup, but a key point is defining when each router should activate.

In my sample app I only have a single route defined for the Angular router. In order to prevent the Angular router from activating when navigating to ui-router routes, I have defined a url filter.

This filter comes in the form of a UrlHandlingStrategy.

I am also defining a bootstrap component that will render the necessary outlets for the routers (ui-view and router-outlet).

import {NgModule, Component} from '@angular/core'; import {UpgradeModule} from '@angular/upgrade/static'; import {platformBrowser, BrowserModule} from '@angular/platform-browser'; import {RouterUpgradeInitializer} from '@angular/router/upgrade'; import {RouterModule, UrlHandlingStrategy} from '@angular/router'; export class Ng1Ng2UrlHandlingStrategy implements UrlHandlingStrategy { shouldProcessUrl(url) { return url.toString().startsWith("/cars"); } extract(url) { return url; } merge(url, whole) { return url; } } import {CarsModule} from './cars/cars.module'; @Component({ selector: 'outlet', template: `<router-outlet></router-outlet> <div ui-view></div>` }) export class OutletComponent {} @NgModule({ declarations: [OutletComponent], entryComponents: [], imports: [BrowserModule, UpgradeModule, CarsModule, RouterModule.forRoot([])], bootstrap: [OutletComponent], providers: [ { provide: UrlHandlingStrategy, useClass: Ng1Ng2UrlHandlingStrategy } ], }) export class AppModule { constructor(public upgrade: UpgradeModule){} }

The actual route is defined in the CarsModule

import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {RouterModule} from '@angular/router'; import {CarsComponent} from './cars.component'; @NgModule({ imports: [ CommonModule, RouterModule.forChild([ { path: 'cars', component: CarsComponent} ]) ], declarations: [CarsComponent] }) export class CarsModule {}


Next I will configure ui-router with the necessary states.

angular.module('awesome', ['ui.router']); angular.module('awesome').config(function($stateProvider, $urlRouterProvider, $locationProvider) { $locationProvider.html5Mode(true); $stateProvider .state('home', { url: '/', templateUrl: '/src/home/home.html' }) .state('cars', { url:'/cars', //Used to clear out ui-view when the angular router is activated template: '' }) .state('friends', { url: '/friends/:name', templateUrl: '/src/friends/friends.html' }); });

You may notice that one of my states overlaps with the 'cars” route from the Angular router configuration. This may seem a bit weird since I am mapping the state to an empty template.

Ideally you don't want overlapping routes, but this hack seems necessary to clear out the ui-view when navigating using the Angular router.

Anyway, there you have it - a simple application, combining ui-router with the Angular router.

I have put the source code on Github in case you are interested in checking it out.

As a bonus I've thrown in two screenshots of the final application as well :-)

Angular Router

I invite you to follow me on twitter