Downgrade Angular 2 providers to Angular 1 services with downgradeInjectable
If you have followed the steps in Connecting Angular 1 and Angular 2 with UpgradeModule, you should now have a hybrid application that is capable of sharing different elements with the opposing framework. If you are unfamiliar with Angular 2 providers, it is recommended that you go through the dependency injection chapter before you proceed.
Like with templated components, interchangeability is also offered to service types. It is possible to define a service type in Angular 2 and then inject it into an Angular 1 context.
Note
The code, links, and a live example in relation to this recipe are available at http://ngcookbook.herokuapp.com/2824/.
Getting ready
Begin with the code written in Connecting Angular 1 and Angular 2 with UpgradeModule.
How to do it...
First, define the service you would like to inject into an Angular 1 component:
[app/article.service.ts] import {Injectable} from '@angular/core'; @Injectable() export class ArticleService { article:Object = { title: 'Research Shows Moon Not Actually Made of Cheese', author: 'Jake Hsu' }; }
Next, define the Angular 1 component that should inject it:
[app/article.component.ts] export const ng1Article = { template: ` <h1>{{article.title}}</h1> <p>{{article.author}}</p> `, controller: (ArticleService, $scope) => { $scope.article = ArticleService.article; } };
ArticleService
won't be injected yet though, since Angular 1 has no idea that this service exists. Doing this is very simple, however. First, you'll list the service provider in the Angular 2 module definition as you normally would:
[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'; import {ArticleService} from './article.service'; @NgModule({ imports: [ BrowserModule, UpgradeModule, ], declarations: [ RootComponent ], providers: [ ArticleService ], bootstrap: [ RootComponent ] }) export class Ng2AppModule { constructor(public upgrade: UpgradeModule){} }
Still, Angular 1 does not understand how to use the service.
In the same way you convert an Angular 2 component definition into an Angular 1 directive, convert an Angular 2 service into an Angular 1 factory. Use downgradeInjectable
and add the Angular 1 component and the converted service to the Angular 1 module definition:
[app/ng1.module.ts] import 'angular'; import {ng1Article} from './article.component'; import {ArticleService} from './article.service'; import {downgradeInjectable} from '@angular/upgrade/static'; export const Ng1AppModule = angular.module('Ng1AppModule', []) .component('ng1Article', ng1Article) .factory('ArticleService', downgradeInjectable(ArticleService));
That's all! You should be able to see the Angular 1 component render with the data passed from the Angular 2 service.
See also
- Connecting Angular 1 and Angular 2 with UpgradeModule shows you how to run Angular 1 and 2 frameworks together
- Downgrading Angular 2 components to Angular 1 directives with downgradeComponent demonstrates how to use an Angular 2 component inside an Angular 1 application