Function
@angular/upgrade/static upgrade helpers
supports AOT
upgrade/downgrade
- provideNg2Component
- downgradeNg2Component
- provideNg2Injectable
- downgradeNg2Injectable
- upgradeInjectable
bootstrap
What it does
Bootstraps hybrid ng1 ( with ngMetadata ) ng2 app
How to use
// main.ts
import { UpgradeModule } from '@angular/upgrade/static/';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from 'ng-metadata/core';
import { Ng1AppModule } from './app/app.module';
import { AppModule } from './app/app.module.ng2';
if ( ENV === 'production' ) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, [Ng1AppModule.name], {strictDi: true});
});
// ./app/app.module.ts
import { downgradeComponent, downgradeInjectable } from '@angular/upgrade/static/';
import { provideNg2Component, provideNg2Injectable } from 'ng-metadata/upgrade'
import { NgModule, Directive, provide, getInjectableName, bundle } from 'ng-metadata/core';
import { AppComponent } from './app.component';
import { Logger, LoggerToken } from './logger.service.ng2';
import { LoginComponent } from './login.component.ng2';
import { HeroesService } from './heroes/heroes.service';
@NgModule( {
declarations: [
AppComponent,
provideNg2Component({component: LoginComponent, downgradeFn: downgradeComponent}),
],
providers: [
HeroesService,
provideNg2Injectable({injectable: Logger, downgradeFn: downgradeInjectable}),
]
} )
class AppModule {
}
// we are using bundle to export regular ng1 module
export const Ng1AppModule = bundle(AppModule);
provideNg2Component
What it does
Used to register an Angular 2 Component by including it in the declarations
array of an ng-metadata @NgModule
,
where the directive name and bindings(inputs,outputs) are automatically created from the selector.
How to use
// app.module.ts
import { downgradeComponent } from '@angular/upgrade/static/';
import { provideNg2Component } from 'ng-metadata/upgrade';
import { NgModule } from 'ng-metadata/core';
import { Ng2Component } from './components/ng2.component';
@NgModule({
declarations:[
provideNg2Component({component:Ng2Component,downgradeFn:downgradeComponent})
]
})
export class AppModule {};
API
type downgradeComponent = (info: {
component: Type;
inputs?: string[];
outputs?: string[];
}) => any;
type ProvideNg2ComponentParams = {
component:Type,
downgradeFn:downgradeComponent
}
export function provideNg2Component({component,downgradeFn}: ProvideNg2ComponentParams): Function
Takes a Angular 2 component and downgradeFn reference to downgradeComponent
from @angular/upgrade/static
Returns a factory function that can be used to register the downgraded ng2 component on an Angular 1 via ngMetadata @NgModule.declarations
.
downgradeNg2Component
What it does
Used to register an Angular 2 Component as a directive on an Angular 1 module, where the directive name and bindings(inputs,outputs) are automatically created from the selector.
How to use
// app.module.ts
import * as angular from 'angular'
import { downgradeComponent } from '@angular/upgrade/static/';
import { downgradeNg2Component } from 'ng-metadata/upgrade';
import { provide } from 'ng-metadata/core';
import { Ng2Component } from './components/ng2.component';
export const AppModule = angular
.module('myApp',[])
.directive(...downgradeNg2Component({component:Ng2Component,downgradeFn:downgradeComponent}))
API
type downgradeComponent = (info: {
component: Type;
inputs?: string[];
outputs?: string[];
}) => any;
type ProvideNg2ComponentParams = {
component:Type,
downgradeFn:downgradeComponent
}
export function downgradeNg2Component({component, downgradeFn}: ProvideNg2ComponentParams): [string, Function]
Takes a Angular 2 component and downgradeFn reference to downgradeComponent
from @angular/upgrade/static
Returns a tuple of component name and factory function that can be used to register the downgraded ng2 component on an Angular 1 module.
provideNg2Injectable
What it does
Used to register an Angular 2 Service by including it in the providers
array of an ng-metadata @NgModule
,
where the service name and downgraded factory functions are automatically generated.
NOTE: downgraded service must also be registered within Angular 2 Component or NgModule
How to use
// app.module.ts - Angular 1(ngMetadata)
import { downgradeInjectable } from '@angular/upgrade/static/';
import { provideNg2Injectable } from 'ng-metadata/upgrade';
import { NgModule } from 'ng-metadata/core';
import { Ng2Service } from './services/ng2.service';
import { Ng2ServiceDecorated } from './services/ng2decorated.service'
const OtherServiceToken = new OpaqueToken('otherService')
@NgModule({
providers: [
provideNg2Injectable({token:'ng2Service', injectable: Ng2Service, downgradeFn: downgradeInjectable }),
provideNg2Injectable({token:OtherServiceToken, injectable: Ng2Service, downgradeFn: downgradeInjectable }),
provideNg2Injectable({injectable:Ng2ServiceDecorated, downgradeFn: downgradeInjectable}),
],
})
export class AppModule{}
as you've may noticed in one registration we've omitted token
, how is that possible that it works you ask?
this is thanks to ngMetadata @Injectable()
decorator, we can decorate Angular 2 Classes with our ngMetadata @Injectable
,
which gives us benefit to omit Opaque tokens creation and use the same class for DI for both Angular 2 and Angular 1.
POWER OVERWHELMING RIGHT?!
Enough Talk! Show me how the service looks like:
// ./services/ng2decorated.service.ts
import {Injectable} from '@angular/core';
import {Injectable as KeepNg1Injectable} from 'ng-metadata/core';
@KeepNg1Injectable()
@Injectable()
export class Ng2ServiceDecorated {
constructor(){}
greet(){}
}
API
type ProviderLiteral = {
provide: any;
useClass?: Type;
useValue?: any;
useFactory?: Function;
useExisting?: any;
deps?: Object[];
multi?: boolean;
}
type ProvideNg2InjectableParams = {
injectable: Function | Type;
downgradeFn: Function;
/**
* We need token only if downgraded Angular 2 Service is not Decorated with both ng2 @Injectable and ngMetadata @Injectable
*
*/
token?: string | OpaqueToken;
};
export function provideNg2Injectable({injectable, downgradeFn, token}: ProvideNg2InjectableParams): ProviderLiteral;
Takes a Angular 2 service, downgradeFn reference to downgradeInjectable
from @angular/upgrade/static
and optional token
that identifies a service provided from Angular 2+.
Returns a ProviderLiteral
which can be used to register an Angular 2 Provider/Injectable
by including it in the providers array of an ng-metadata annotated Angular 1
@Component
or @NgModule
. Either a string or an ng-metadata OpaqueToken can be used for the name.
downgradeNg2Injectable
What it does
Downgrades an Angular 2 Injectable so that it can be registered as an Angular 1
factory. Either a string or an ng-metadata OpaqueToken
can be used for the name.
NOTE: downgraded service must also be registered within Angular 2 @Component
or @NgModule
How to use
// app.module.ts
import * as angular from 'angular'
import { downgradeInjectable } from '@angular/upgrade/static/';
import { downgradeNg2Injectable } from 'ng-metadata/upgrade';
import { provide } from 'ng-metadata/core';
import { Ng2Service } from './services/ng2.service';
import { Ng2ServiceDecorated } from './services/ng2decorated.service';
export const OtherServiceToken = new OpaqueToken('otherService')
export const AppModule = angular
.module('myApp',[])
.factory(...downgradeNg2Injectable({token:'ng2Service', injectable: Ng2Service, downgradeFn: downgradeInjectable }))
.factory(...downgradeNg2Injectable({token: OtherServiceToken, injectable: Ng2Service, downgradeFn: downgradeInjectable }))
.factory(...downgradeNg2Injectable({injectable:Ng2ServiceDecorated, downgradeFn: downgradeInjectable}))
API
type ProvideNg2InjectableParams = {
injectable: Function | Type;
downgradeFn: Function;
/**
* We need token only if downgraded Angular 2 Service is not Decorated with both ng2 @Injectable and ngMetadata @Injectable
*
*/
token?: string | OpaqueToken;
};
export function downgradeNg2Injectable( { injectable, downgradeFn, token }: ProvideNg2InjectableParams ): [string|Function]
Takes a Angular 2 service, downgradeFn reference to downgradeInjectable
from @angular/upgrade/static
and optional token
that identifies a service provided from Angular 2+.
Returns a tuple of service name and factory function that can be used to register the downgraded ng2 service on an Angular 1 module.
upgradeInjectable
What it does
Helper function to upgrade Angular 1 services to Angular 2 without need of using lot of boilerplate
How to use
Let's say we have ngMetadata angular 1 Service:
// heroes.service.ts
import { Injectable } from 'ng-metadata/core'
import { Hero } from './hero';
@Injectable()
export class HeroesService {
get() {
return [
new Hero(1, 'Windstorm'),
new Hero(2, 'Spiderman'),
];
}
}
registered within ng-metadata NgModule:
// app.module.ts
import { NgModule } from 'ng-metadata/core';
import { HeroesService } from './heroes/heroes.service';
@NgModule( {
providers: [ HeroesService ]
} )
class AppModule {}
and we can upgrade it to Angular 2 like this:
// app.module.ng2.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static/';
import { provideNg1Injectable } from 'ng-metadata/upgrade';
import { HeroComponent } from './heroes/hero.component.ng2';
import { HeroesService } from './heroes/heroes.service';
@NgModule({
imports: [
BrowserModule,
UpgradeModule
],
declarations: [
HeroComponent
],
providers: [
provideNg1Injectable('$routeParams'),
provideNg1Injectable(HeroesService),
],
entryComponents: [
HeroComponent
]
})
export class AppModule {
// preventing automatic Bootstrap
ngDoBootstrap() {}
}
and now we can use it within angular 2 Component:
// hero.component.ng2.ts
import { Component, Inject } from '@angular/core';
@Component({
selector: 'my-hero',
template: `<h1>My Hero</h1>`,
})
class HeroComponent {
constructor(
@Inject('$routeParams') private $routeParams: any, // by name using @Inject
private myCoolSvc: MyCoolService, // by type using the user defined token
private heroesSvc: HeroesService // by type using ngMetadata @Injectable service class
) {}
}