Angular 2 comes with the ability to connect it to an existing Angular 1 application. This is obviously advantageous since this will allow you to utilize existing components and services in Angular 1 in tandem with Angular 2's components and services. UpgradeModule
is the tool that is supported by Angular teams to accomplish such a feat.
The code, links, and a live example in relation to this recipe are available at .
Suppose you had a very simple Angular 1 application as follows:
[index.html] <!DOCTYPE html> <html> <head> <!-- Angular 1 scripts --> <script src="angular.js"></script> </head> <body> <div ng-app="hybridApp" ng-init="val='Angular 1 bootstrapped successfully!'"> {{val}} </div> </body> </html>
This application interpolates a value set in an Angular expression so you can visually confirm that the application has bootstrapped and is working.
Begin by declaring the top-level angular module inside its own file. Instead of using a script tag to fetch the angular module, require Angular 1, import it, and create the root Angular 1 module:
[ng1.module.ts] import 'angular' export const Ng1AppModule = angular.module('Ng1AppModule', []);
Angular 2 ships with an upgrade module out of the box, which is provided inside upgrade.js
. The two frameworks can be connected with UpgradeModule
.
This recipe utilizes SystemJS and TypeScript, the specifications for which lie inside a very complicated config file. This is discussed in a later chapter, so don't worry about the specifics. For now, you are free to assume the following:
.ts
) files on the flyimport
and export
statements in TypeScript filesAngular 2 requires a top-level module definition as part of its base configuration:
[app/ng2.module.ts] import {NgModule} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {UpgradeModule} from '@angular/upgrade/static'; import {RootComponent} from './root.component'; @NgModule({ imports: [ BrowserModule, UpgradeModule, ], bootstrap: [ RootComponent ], declarations: [ RootComponent ] }) export class Ng2AppModule { constructor(public upgrade: UpgradeModule){} } export class AppModule {}
The reason why this module definition exists this way isn't critical for understanding this recipe. Angular 2 modules are covered in , Services, Dependency Injection, and NgModule.
Create the root component of the Angular 2 application:
[app/root.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'root', template: ` <p>Angular 2 bootstrapped successfully!</p> ` }) export class RootComponent {}
Since Angular 2 will often bootstrap from a top-level file, create this file as main.ts
and bootstrap the Angular 2 module:
[main.ts] import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {Ng1AppModule} from './app/ng1.module'; import {Ng2AppModule} from './app/ng2.module'; platformBrowserDynamic() .bootstrapModule(Ng2AppModule);
Don't use an ng-app to bootstrap the Angular 1 application; instead, do this after you bootstrap Angular 2:
[main.ts] import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {Ng1AppModule} from './app/ng1.module'; import {Ng2AppModule} from './app/ng2.module'; platformBrowserDynamic() .bootstrapModule(Ng2AppModule) .then(ref => { ref.instance.upgrade .bootstrap(document.body, [Ng1AppModule.name]); });
With this, you'll be able to remove Angular 1's JS script, the ng-app
directive, and add in the root element of the Angular 2 app:
[index.html] <!DOCTYPE html> <html> <head> <!-- Angular 2 scripts --> <script src="zone.js "></script> <script src="reflect-metadata.js"></script> <script src="system.js"></script> <script src="system-config.js"></script> </head> <body> <div ng-init="val='Angular 1 bootstrapped successfully!'"> {{val}} </div> <root></root> </body> </html>
The new scripts listed here are dependencies of an Angular 2 application, but understanding what they're doing isn't critical for understanding this recipe. This is explained later in the book.
With all this, you should see your Angular 1 application template compile and the Angular 2 component render properly again. This means that you are successfully running Angular 1 and Angular 2 frameworks side by side.
Make no mistake, when you use UpgradeModule
, you create an Angular 1 and Angular 2 app on the same page and connect them together. This adapter instance will allow you to connect pieces from each framework and use them in harmony.
More specifically, this creates an Angular 1 application at the top level and allows you to uses pieces of an Angular 2 application inside it.
While useful for experimentation and upgrading purposes, this should not be a solution that any application should rely on in a production context. You have effectively doubled the framework payload size and introduced additional complexity in an existing application. Although Angular 2 is a far more performant framework, do not expect to have the same pristine results with the UpgradeModule
cross-pollination.
That said, as you will see in subsequent recipes, you can now use Angular 2 components in an Angular 1 application using the adapter translation methods.