├── new ├── system.config.v4.js ├── app-module.ts └── bootstrap.ts ├── old ├── bootstrap.ts └── upgrade-adapter.ts ├── upgrade ├── provider │ ├── document-converter.v1.ts │ └── app-module.v4.ts └── directive │ ├── document-stars.v1.ts │ ├── app-module.v4.ts │ └── document-stars.v4.ts ├── downgrade ├── provider │ ├── documents-service.v4.ts │ ├── hybrid.v4.ts │ └── app-module.v4.ts └── component │ ├── hybrid.v4.ts │ ├── app-module.v4.ts │ └── document-component.v4.ts ├── README.md ├── canonical-example └── hybrid.v4.ts └── hybrid-helper.ts /new/system.config.v4.js: -------------------------------------------------------------------------------- 1 | System.config({ 2 | map: { 3 | '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js' 4 | } 5 | }); 6 | -------------------------------------------------------------------------------- /old/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { upgradeAdapter } from './upgrade-adapter.old.ts'; 2 | 3 | upgradeAdapter.bootstrap(document.body, ['myApp'], { strictDi: true }); 4 | -------------------------------------------------------------------------------- /upgrade/provider/document-converter.v1.ts: -------------------------------------------------------------------------------- 1 | angular.module('documents') 2 | .service('DocumentConverter', [() => { 3 | //... 4 | }]); 5 | -------------------------------------------------------------------------------- /downgrade/provider/documents-service.v4.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable() 4 | export class DocumentsService { 5 | //... 6 | } 7 | -------------------------------------------------------------------------------- /upgrade/directive/document-stars.v1.ts: -------------------------------------------------------------------------------- 1 | export const documentStars = { 2 | template: ` 3 | {{ num }} 4 | ... 5 | `, 6 | controller: () => { 7 | //... 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angularjs-to-angular4 2 | Source code for my article about building [hybrid upgrade Angular v4 application](https://medium.com/@dormoshe/angular-v4-hybrid-upgrade-application-73d5afba1e01) 3 | -------------------------------------------------------------------------------- /downgrade/provider/hybrid.v4.ts: -------------------------------------------------------------------------------- 1 | import { HybridHelper } from '../../hybrid-helper'; 2 | import { DocumentsService } from './documents-service.v4'; 3 | 4 | const moduleName = 'document'; 5 | HybridHelper.downgradeProvider(moduleName, 'DocumentsService', DocumentsService); 6 | -------------------------------------------------------------------------------- /upgrade/provider/app-module.v4.ts: -------------------------------------------------------------------------------- 1 | import { HybridHelper } from '../../hybrid-helper'; 2 | 3 | const myServices = [ 4 | HybridHelper.buildProviderForUpgrade('DocumentConverter') 5 | ]; 6 | 7 | @NgModule({ 8 | // services 9 | providers: [ 10 | ...myServices 11 | ], 12 | // … 13 | }); 14 | -------------------------------------------------------------------------------- /upgrade/directive/app-module.v4.ts: -------------------------------------------------------------------------------- 1 | import { HybridHelper } from './hybrid-helper.v4'; 2 | import { DocumentStarsDirective } from './document-stars.v4'; 3 | 4 | const myDirectives = [ 5 | DocumentStarsDirective 6 | ]; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | ...myDirectives 11 | ], 12 | … 13 | }); 14 | -------------------------------------------------------------------------------- /new/ app-module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { UpgradeModule } from '@angular/upgrade/static'; 4 | 5 | @NgModule({ 6 | imports: [ 7 | BrowserModule, 8 | UpgradeModule 9 | ], 10 | bootstrap: [] 11 | }) 12 | export class AppModule { 13 | ngDoBootstrap() {} 14 | } 15 | -------------------------------------------------------------------------------- /old/upgrade-adapter.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, forwardRef } from '@angular/core'; 2 | import { UpgradeAdapter } from '@angular/upgrade'; 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | 5 | export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule)); 6 | 7 | @NgModule({ 8 | imports: [ 9 | BrowserModule 10 | ], 11 | bootstrap: [] 12 | }) 13 | export class AppModule {} 14 | -------------------------------------------------------------------------------- /new/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { UpgradeModule } from '@angular/upgrade/static'; 3 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => { 6 | const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule; 7 | upgrade.bootstrap(document.body, ['myApp'], { strictDi: true }); 8 | }); 9 | -------------------------------------------------------------------------------- /downgrade/component/hybrid.v4.ts: -------------------------------------------------------------------------------- 1 | import { HybridHelper } from '../../hybrid-helper'; 2 | import { DocumentComponent } from './document-component.v4'; 3 | 4 | const moduleName = 'document'; 5 | angular.module(moduleName, [...]); 6 | 7 | HybridHelper.downgradeComponent(moduleName, 'document', DocumentComponent, { 8 | inputs: ['name', 'size', 'numOfPages', 'content'], 9 | outputs: ['opened', 'contentChanged', 'closed'] 10 | }); 11 | -------------------------------------------------------------------------------- /downgrade/provider/app-module.v4.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { UpgradeModule } from '@angular/upgrade/static'; 4 | 5 | import { DocumentsService } from './documents-service.v4'; 6 | 7 | @NgModule({ 8 | providers: [ DocumentsService ], 9 | imports: [ 10 | BrowserModule, 11 | UpgradeModule 12 | ], 13 | bootstrap: [] 14 | }) 15 | export class AppModule { 16 | ngDoBootstrap() {} 17 | } 18 | -------------------------------------------------------------------------------- /upgrade/directive/document-stars.v4.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, Injector, Input, Output, EventEmitter } from '@angular/core'; 2 | import { UpgradeComponent } from '@angular/upgrade/static'; 3 | 4 | @Directive({ 5 | selector: 'document-stars' 6 | }) 7 | export class DocumentStarsDirective extends UpgradeComponent { 8 | @Input() num: number; 9 | @Output() clicked: EventEmitter; 10 | 11 | constructor(elementRef: ElementRef, injector: Injector) { 12 | super('documentStars', elementRef, injector); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /downgrade/component/app-module.v4.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { UpgradeModule } from '@angular/upgrade/static'; 4 | 5 | import { DocumentComponent } from './document-component.v4'; 6 | 7 | @NgModule({ 8 | declarations: [ DocumentComponent ], 9 | entryComponents: [ DocumentComponent ], 10 | imports: [ 11 | BrowserModule, 12 | UpgradeModule 13 | ], 14 | bootstrap: [] 15 | }) 16 | export class AppModule { 17 | ngDoBootstrap() {} 18 | } 19 | -------------------------------------------------------------------------------- /downgrade/component/document-component.v4.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | selector: 'document', 6 | template: `...`//, 7 | //styles: `...` 8 | }) 9 | 10 | export class DocumentComponent { 11 | @Input() name: string; 12 | @Input() size: number; 13 | @Input() numOfPages: number; 14 | @Input() content: string; 15 | 16 | @Output() opened = new EventEmitter(); 17 | @Output() contentChanged = new EventEmitter(); 18 | @Output() closed = new EventEmitter(); 19 | 20 | //... 21 | } 22 | -------------------------------------------------------------------------------- /canonical-example/hybrid.v4.ts: -------------------------------------------------------------------------------- 1 | import { HybridHelper } from '../hybrid-helper.v4'; 2 | import { DocumentsService, AnotherService } from './services'; 3 | import { DocumentComponent, AnotherComponent, AnotherComponent2, AnotherComponent3 } from './components'; 4 | 5 | const moduleName = 'document'; 6 | angular.module(moduleName, [...]); 7 | 8 | HybridHelper 9 | .downgradeComponent(moduleName, 'document', DocumentComponent, { 10 | inputs: ['name', 'size', 'numOfPages', 'content'], 11 | outputs: ['opened', 'contentChanged', 'closed'] 12 | }) 13 | .downgradeComponent(moduleName, 'another', AnotherComponent, { 14 | inputs: ['inp1', 'inp2'] 15 | }) 16 | .downgradeComponent(moduleName, 'another2', AnotherComponent2, { 17 | outputs: ['out1', 'out2'] 18 | }) 19 | .downgradeComponent(moduleName, 'another3', AnotherComponent3) 20 | .downgradeProvider(moduleName, 'DocumentsService', DocumentsService) 21 | .downgradeProvider(moduleName, 'AnotherService', AnotherService); 22 | -------------------------------------------------------------------------------- /hybrid-helper.ts: -------------------------------------------------------------------------------- 1 | import { downgradeComponent, downgradeInjectable } from '@angular/upgrade/static'; 2 | import { FactoryProvider } from '@angular/core'; 3 | 4 | export interface IComponentUpgradeOptions { 5 | inputs?: string[], 6 | outputs?: string[] 7 | } 8 | 9 | export interface IHybridHelper { 10 | downgradeComponent(moduleName: string, componentSelector: string, componentClass: any, options?: IComponentUpgradeOptions): IHybridHelper, 11 | downgradeProvider(moduleName: string, providerName: string, providerClass: any): IHybridHelper, 12 | buildProviderForUpgrade(ng1Name: string, ng2Name?: string): FactoryProvider 13 | } 14 | 15 | export const HybridHelper: IHybridHelper { 16 | 17 | downgradeComponent: (moduleName: string, componentName: string, componentClass: any, options?: IComponentUpgradeOptions): IHybridHelper => { 18 | options = options || {}; 19 | const inputs = options.inputs || []; 20 | const outputs = options.outputs || []; 21 | const component = componentClass; 22 | 23 | angular.module(moduleName).directive(componentName, downgradeComponent({ 24 | component, inputs, outputs 25 | }) as angular.IDirectiveFactory); 26 | 27 | return HybridHelper; 28 | }, 29 | 30 | downgradeProvider: (moduleName: string, providerName: string, providerClass: any): IHybridHelper => { 31 | angular.module(moduleName).factory(providerName, downgradeInjectable(providerClass)); 32 | 33 | return HybridHelper; 34 | }, 35 | 36 | buildProviderForUpgrade: (ng1Name: string, ng2Name?: string): FactoryProvider => { 37 | ng2Name = ng2Name || ng1Name; 38 | 39 | return { 40 | provide: ng2Name, 41 | useFactory: buildFactoryForUpgradeProvider(ng1Name), 42 | deps: ['$injector'] 43 | }; 44 | } 45 | } 46 | 47 | function buildFactoryForUpgradeProvider(ng1Name: string): Function { 48 | return (injector: any) => injector.get(ng1Name); 49 | } 50 | --------------------------------------------------------------------------------