diff --git a/packages/examples/upgrade/static/ts/e2e_test/static_spec.ts b/packages/examples/upgrade/static/ts/full/e2e_test/static_full_spec.ts similarity index 87% rename from packages/examples/upgrade/static/ts/e2e_test/static_spec.ts rename to packages/examples/upgrade/static/ts/full/e2e_test/static_full_spec.ts index ed780162e6..5558ffb5b4 100644 --- a/packages/examples/upgrade/static/ts/e2e_test/static_spec.ts +++ b/packages/examples/upgrade/static/ts/full/e2e_test/static_full_spec.ts @@ -7,16 +7,15 @@ */ import {browser, by, element} from 'protractor'; -import {verifyNoBrowserErrors} from '../../../../_common/e2e_util'; +import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util'; -function loadPage(url: string) { - browser.ng12Hybrid = true; +function loadPage() { browser.rootEl = 'example-app'; - browser.get(url); + browser.get('/upgrade/static/ts/full/'); } -describe('upgrade(static)', () => { - beforeEach(() => { loadPage('/upgrade/static/ts/'); }); +describe('upgrade/static (full)', () => { + beforeEach(loadPage); afterEach(verifyNoBrowserErrors); it('should render the `ng2-heroes` component', () => { diff --git a/packages/examples/upgrade/static/ts/module.ts b/packages/examples/upgrade/static/ts/full/module.ts similarity index 85% rename from packages/examples/upgrade/static/ts/module.ts rename to packages/examples/upgrade/static/ts/full/module.ts index e8bf6cfcf4..7e842c4cee 100644 --- a/packages/examples/upgrade/static/ts/module.ts +++ b/packages/examples/upgrade/static/ts/full/module.ts @@ -5,11 +5,14 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import {Component, Directive, ElementRef, EventEmitter, Inject, Injectable, Injector, Input, NgModule, Output, SimpleChanges} from '@angular/core'; + +import {Component, Directive, ElementRef, EventEmitter, Inject, Injectable, Injector, Input, NgModule, Output} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {UpgradeComponent, UpgradeModule, downgradeComponent, downgradeInjectable} from '@angular/upgrade/static'; +declare var angular: ng.IAngularStatic; + interface Hero { name: string; description: string; @@ -116,7 +119,6 @@ class Ng2AppModule { // #docregion Angular 1 Stuff // #docregion ng1-module // This Angular 1 module represents the AngularJS pieces of the application -declare var angular: ng.IAngularStatic; const ng1AppModule = angular.module('ng1AppModule', []); // #enddocregion @@ -136,7 +138,7 @@ ng1AppModule.component('ng1Hero', { // This AngularJS service will be "upgraded" to be used in Angular ng1AppModule.factory( 'titleCase', - (() => (value: string) => value.replace(/((^|\s)[a-z])/g, (_, c) => c.toUpperCase())) as any); + () => (value: string) => value.replace(/((^|\s)[a-z])/g, (_, c) => c.toUpperCase())); // #enddocregion // #docregion downgrade-ng2-heroes-service @@ -145,7 +147,7 @@ ng1AppModule.factory('heroesService', downgradeInjectable(HeroesService) as any) // #enddocregion // #docregion ng2-heroes-wrapper -// This is directive will act as the interface to the "downgraded" Angular component +// This directive will act as the interface to the "downgraded" Angular component ng1AppModule.directive('ng2Heroes', downgradeComponent({component: Ng2HeroesComponent})); // #enddocregion @@ -155,20 +157,18 @@ ng1AppModule.component('exampleApp', { // We inject the "downgraded" HeroesService into this AngularJS component // (We don't need the `HeroesService` type for AngularJS DI - it just helps with TypeScript // compilation) - controller: - [ - 'heroesService', - function(heroesService: HeroesService) { this.heroesService = heroesService; } - ], - // This template make use of the downgraded `ng2-heroes` component - // Note that because its element is compiled by AngularJS we must use kebab-case attributes - // for inputs and outputs - template: ` - -

Heroes

-

There are {{ $ctrl.heroesService.heroes.length }} heroes.

-
` -} as any); + controller: [ + 'heroesService', function(heroesService: HeroesService) { this.heroesService = heroesService; } + ], + // This template makes use of the downgraded `ng2-heroes` component + // Note that because its element is compiled by AngularJS we must use kebab-case attributes + // for inputs and outputs + template: ` + +

Heroes

+

There are {{ $ctrl.heroesService.heroes.length }} heroes.

+
` +}); // #enddocregion // #enddocregion diff --git a/packages/examples/upgrade/static/ts/styles.css b/packages/examples/upgrade/static/ts/full/styles.css similarity index 100% rename from packages/examples/upgrade/static/ts/styles.css rename to packages/examples/upgrade/static/ts/full/styles.css diff --git a/packages/examples/upgrade/static/ts/lite/e2e_test/e2e_util.ts b/packages/examples/upgrade/static/ts/lite/e2e_test/e2e_util.ts new file mode 100644 index 0000000000..bc53502d01 --- /dev/null +++ b/packages/examples/upgrade/static/ts/lite/e2e_test/e2e_util.ts @@ -0,0 +1,64 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ElementFinder, by} from 'protractor'; + +declare global { + namespace jasmine { + interface Matchers { + toBeAHero(): Promise; + toHaveName(exectedName: string): Promise; + } + } +} + +const isTitleCased = (text: string) => + text.split(/\s+/).every(word => word[0] === word[0].toUpperCase()); + +export function addCustomMatchers() { + jasmine.addMatchers({ + toBeAHero: + () => ({ + compare(actualNg1Hero: ElementFinder | undefined) { + const getText = (selector: string) => + actualNg1Hero !.element(by.css(selector)).getText(); + const result = { + message: 'Expected undefined to be an `ng1Hero` ElementFinder.', + pass: !!actualNg1Hero && + Promise.all(['.title', 'h2', 'p'].map(getText) as PromiseLike[]) + .then(([actualTitle, actualName, actualDescription]) => { + const pass = (actualTitle === 'Super Hero') && isTitleCased(actualName) && + (actualDescription.length > 0); + + const actualHero = + `Hero(${actualTitle}, ${actualName}, ${actualDescription})`; + result.message = + `Expected ${actualHero}'${pass ? ' not' : ''} to be a real hero.`; + + return pass; + }) + }; + return result; + } + }), + toHaveName: () => ({ + compare(actualNg1Hero: ElementFinder | undefined, expectedName: string) { + const result = { + message: 'Expected undefined to be an `ng1Hero` ElementFinder.', + pass: !!actualNg1Hero && actualNg1Hero.element(by.css('h2')).getText().then(actualName => { + const pass = actualName === expectedName; + result.message = + `Expected Hero(${actualName})${pass ? ' not' : ''} to have name '${expectedName}'.`; + return pass; + }) + }; + return result; + } + }), + } as any); +} diff --git a/packages/examples/upgrade/static/ts/lite/e2e_test/static_lite_spec.ts b/packages/examples/upgrade/static/ts/lite/e2e_test/static_lite_spec.ts new file mode 100644 index 0000000000..5e7b6395ef --- /dev/null +++ b/packages/examples/upgrade/static/ts/lite/e2e_test/static_lite_spec.ts @@ -0,0 +1,89 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ElementArrayFinder, ElementFinder, browser, by, element} from 'protractor'; + +import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util'; +import {addCustomMatchers} from './e2e_util'; + +function loadPage() { + browser.rootEl = 'example-app'; + browser.get('/upgrade/static/ts/lite/'); +} + +describe('upgrade/static (lite)', () => { + let showHideBtn: ElementFinder; + let ng2Heroes: ElementFinder; + let ng2HeroesHeader: ElementFinder; + let ng2HeroesExtra: ElementFinder; + let ng2HeroesAddBtn: ElementFinder; + let ng1Heroes: ElementArrayFinder; + + const expectHeroes = (isShown: boolean, ng1HeroCount = 3, statusMessage = 'Ready') => { + // Verify the show/hide button text. + expect(showHideBtn.getText()).toBe(isShown ? 'Hide heroes' : 'Show heroes'); + + // Verify the `` component. + expect(ng2Heroes.isPresent()).toBe(isShown); + if (isShown) { + expect(ng2HeroesHeader.getText()).toBe('Heroes'); + expect(ng2HeroesExtra.getText()).toBe(`Status: ${statusMessage}`); + } + + // Verify the `` components. + expect(ng1Heroes.count()).toBe(isShown ? ng1HeroCount : 0); + if (isShown) { + ng1Heroes.each(ng1Hero => expect(ng1Hero).toBeAHero()); + } + }; + + beforeEach(() => { + showHideBtn = element(by.binding('toggleBtnText')); + + ng2Heroes = element(by.css('.ng2-heroes')); + ng2HeroesHeader = ng2Heroes.element(by.css('h1')); + ng2HeroesExtra = ng2Heroes.element(by.css('.extra')); + ng2HeroesAddBtn = ng2Heroes.element(by.buttonText('Add Hero')); + + ng1Heroes = element.all(by.css('.ng1-hero')); + }); + beforeEach(addCustomMatchers); + beforeEach(loadPage); + afterEach(verifyNoBrowserErrors); + + it('should initially not render the heroes', () => expectHeroes(false)); + + it('should toggle the heroes when clicking the "show/hide" button', () => { + showHideBtn.click(); + expectHeroes(true); + + showHideBtn.click(); + expectHeroes(false); + }); + + it('should add a new hero when clicking the "add" button', () => { + showHideBtn.click(); + ng2HeroesAddBtn.click(); + + expectHeroes(true, 4, 'Added hero Kamala Khan'); + expect(ng1Heroes.last()).toHaveName('Kamala Khan'); + }); + + it('should remove a hero when clicking its "remove" button', () => { + showHideBtn.click(); + + const firstHero = ng1Heroes.first(); + expect(firstHero).toHaveName('Superman'); + + const removeBtn = firstHero.element(by.buttonText('Remove')); + removeBtn.click(); + + expectHeroes(true, 2, 'Removed hero Superman'); + expect(ng1Heroes.first()).not.toHaveName('Superman'); + }); +}); diff --git a/packages/examples/upgrade/static/ts/lite/module.ts b/packages/examples/upgrade/static/ts/lite/module.ts new file mode 100644 index 0000000000..1a21702714 --- /dev/null +++ b/packages/examples/upgrade/static/ts/lite/module.ts @@ -0,0 +1,220 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +// #docplaster +import {Component, Directive, ElementRef, EventEmitter, Inject, Injectable, Injector, Input, NgModule, Output, StaticProvider} from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; +// #docregion basic-how-to +// Alternatively, we could import and use an `NgModuleFactory` instead: +// import {MyLazyAngularModuleNgFactory} from './my-lazy-angular-module.ngfactory'; +import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; +// #enddocregion +/* tslint:disable: no-duplicate-imports */ +import {UpgradeComponent} from '@angular/upgrade/static'; +import {downgradeComponent} from '@angular/upgrade/static'; +import {downgradeInjectable} from '@angular/upgrade/static'; +// #docregion basic-how-to +import {downgradeModule} from '@angular/upgrade/static'; +// #enddocregion +/* tslint:enable: no-duplicate-imports */ + + +declare var angular: ng.IAngularStatic; + +interface Hero { + name: string; + description: string; +} + + +// This Angular service will use an "upgraded" AngularJS service. +@Injectable() +class HeroesService { + heroes: Hero[] = [ + {name: 'superman', description: 'The man of steel'}, + {name: 'wonder woman', description: 'Princess of the Amazons'}, + {name: 'thor', description: 'The hammer-wielding god'} + ]; + + constructor(@Inject('titleCase') titleCase: (v: string) => string) { + // Change all the hero names to title case, using the "upgraded" AngularJS service. + this.heroes.forEach((hero: Hero) => hero.name = titleCase(hero.name)); + } + + addHero() { + const newHero: Hero = {name: 'Kamala Khan', description: 'Epic shape-shifting healer'}; + this.heroes = this.heroes.concat([newHero]); + return newHero; + } + + removeHero(hero: Hero) { this.heroes = this.heroes.filter((item: Hero) => item !== hero); } +} + + +// This Angular component will be "downgraded" to be used in AngularJS. +@Component({ + selector: 'ng2-heroes', + // This template uses the "upgraded" `ng1-hero` component + // (Note that because its element is compiled by Angular we must use camelCased attribute names.) + template: ` +
+
+ +
+ + Super Hero + +
+ +
+ `, +}) +class Ng2HeroesComponent { + @Output() private addHero = new EventEmitter(); + @Output() private removeHero = new EventEmitter(); + + constructor( + @Inject('$rootScope') private $rootScope: ng.IRootScopeService, + public heroesService: HeroesService) {} + + onAddHero() { + const newHero = this.heroesService.addHero(); + this.addHero.emit(newHero); + + // When a new instance of an "upgraded" component - such as `ng1Hero` - is created, we want to + // run a `$digest` to initialize its bindings. Here, the component will be created by `ngFor` + // asynchronously, thus we have to schedule the `$digest` to also happen asynchronously. + this.$rootScope.$applyAsync(); + } + + onRemoveHero(hero: Hero) { + this.heroesService.removeHero(hero); + this.removeHero.emit(hero); + } +} + + +// This Angular directive will act as an interface to the "upgraded" AngularJS component. +@Directive({selector: 'ng1-hero'}) +class Ng1HeroComponentWrapper extends UpgradeComponent { + // The names of the input and output properties here must match the names of the + // `<` and `&` bindings in the AngularJS component that is being wrapped. + @Input() hero: Hero; + @Output() onRemove: EventEmitter; + + constructor(elementRef: ElementRef, injector: Injector) { + // We must pass the name of the directive as used by AngularJS to the super. + super('ng1Hero', elementRef, injector); + } +} + + +// This Angular module represents the Angular pieces of the application. +@NgModule({ + imports: [BrowserModule], + declarations: [Ng2HeroesComponent, Ng1HeroComponentWrapper], + providers: [ + HeroesService, + // Register an Angular provider whose value is the "upgraded" AngularJS service. + {provide: 'titleCase', useFactory: (i: any) => i.get('titleCase'), deps: ['$injector']} + ], + // All components that are to be "downgraded" must be declared as `entryComponents`. + entryComponents: [Ng2HeroesComponent] + // Note that there are no `bootstrap` components, since the "downgraded" component + // will be instantiated by ngUpgrade. +}) +class MyLazyAngularModule { + // Empty placeholder method to prevent the `Compiler` from complaining. + ngDoBootstrap() {} +} + + +// #docregion basic-how-to + + +// The function that will bootstrap the Angular module (when/if necessary). +// (This would be omitted if we provided an `NgModuleFactory` directly.) +const ng2BootstrapFn = (extraProviders: StaticProvider[]) => + platformBrowserDynamic(extraProviders).bootstrapModule(MyLazyAngularModule); +// #enddocregion +// (We are using the dynamic browser platform, as this example has not been compiled AoT.) + + +// #docregion basic-how-to + + +// This AngularJS module represents the AngularJS pieces of the application. +const myMainAngularJsModule = angular.module('myMainAngularJsModule', [ + // We declare a dependency on the "downgraded" Angular module. + downgradeModule(ng2BootstrapFn) + // or + // downgradeModule(MyLazyAngularModuleFactory) +]); +// #enddocregion + + +// This AngularJS component will be "upgraded" to be used in Angular. +myMainAngularJsModule.component('ng1Hero', { + bindings: {hero: '<', onRemove: '&'}, + transclude: true, + template: ` +
+
+

{{ $ctrl.hero.name }}

+

{{ $ctrl.hero.description }}

+ +
+ ` +}); + + +// This AngularJS service will be "upgraded" to be used in Angular. +myMainAngularJsModule.factory( + 'titleCase', () => (value: string) => value.replace(/(^|\s)[a-z]/g, m => m.toUpperCase())); + + +// This directive will act as the interface to the "downgraded" Angular component. +myMainAngularJsModule.directive( + 'ng2Heroes', downgradeComponent({ + component: Ng2HeroesComponent, + // Optionally, disable `$digest` propagation to avoid unnecessary change detection. + // (Change detection is still run when the inputs of a "downgraded" component change.) + propagateDigest: false + })); + + +// This is our top level application component. +myMainAngularJsModule.component('exampleApp', { + // This template makes use of the "downgraded" `ng2-heroes` component, + // but loads it lazily only when/if the user clicks the button. + // (Note that because its element is compiled by AngularJS, + // we must use kebab-case attributes for inputs and outputs.) + template: ` + + + +

Heroes

+

Status: {{ $ctrl.statusMessage }}

+
+ `, + controller: function() { + this.showHeroes = false; + this.statusMessage = 'Ready'; + + this.setStatusMessage = (msg: string) => this.statusMessage = msg; + this.toggleHeroes = () => this.showHeroes = !this.showHeroes; + this.toggleBtnText = () => `${this.showHeroes ? 'Hide' : 'Show'} heroes`; + } +}); + + +// We bootstrap the Angular module as we would do in a normal Angular app. +angular.bootstrap(document.body, [myMainAngularJsModule.name]); diff --git a/packages/examples/upgrade/static/ts/lite/styles.css b/packages/examples/upgrade/static/ts/lite/styles.css new file mode 100644 index 0000000000..f3785c1c22 --- /dev/null +++ b/packages/examples/upgrade/static/ts/lite/styles.css @@ -0,0 +1,17 @@ +ng2-heroes { + border: solid black 2px; + display: block; + padding: 5px; +} + +ng1-hero { + border: solid green 2px; + margin-top: 5px; + padding: 5px; + display: block; +} + +.title { + background-color: blue; + color: white; +} diff --git a/packages/upgrade/src/common/downgrade_component.ts b/packages/upgrade/src/common/downgrade_component.ts index 9a642fca1d..f536ca235b 100644 --- a/packages/upgrade/src/common/downgrade_component.ts +++ b/packages/upgrade/src/common/downgrade_component.ts @@ -34,14 +34,14 @@ interface Thenable { * Let's assume that you have an Angular component called `ng2Heroes` that needs * to be made available in AngularJS templates. * - * {@example upgrade/static/ts/module.ts region="ng2-heroes"} + * {@example upgrade/static/ts/full/module.ts region="ng2-heroes"} * * We must create an AngularJS [directive](https://docs.angularjs.org/guide/directive) * that will make this Angular component available inside AngularJS templates. * The `downgradeComponent()` function returns a factory function that we * can use to define the AngularJS directive that wraps the "downgraded" component. * - * {@example upgrade/static/ts/module.ts region="ng2-heroes-wrapper"} + * {@example upgrade/static/ts/full/module.ts region="ng2-heroes-wrapper"} * * @param info contains information about the Component that is being downgraded: * diff --git a/packages/upgrade/src/common/downgrade_injectable.ts b/packages/upgrade/src/common/downgrade_injectable.ts index 64c13fc7c0..c763067eb2 100644 --- a/packages/upgrade/src/common/downgrade_injectable.ts +++ b/packages/upgrade/src/common/downgrade_injectable.ts @@ -26,21 +26,21 @@ import {INJECTOR_KEY} from './constants'; * that will be part of the upgrade application. For example, let's assume we have * defined `HeroesService` * - * {@example upgrade/static/ts/module.ts region="ng2-heroes-service"} + * {@example upgrade/static/ts/full/module.ts region="ng2-heroes-service"} * * and that we have included this in our upgrade app `NgModule` * - * {@example upgrade/static/ts/module.ts region="ng2-module"} + * {@example upgrade/static/ts/full/module.ts region="ng2-module"} * * Now we can register the `downgradeInjectable` factory function for the service * on an AngularJS module. * - * {@example upgrade/static/ts/module.ts region="downgrade-ng2-heroes-service"} + * {@example upgrade/static/ts/full/module.ts region="downgrade-ng2-heroes-service"} * * Inside an AngularJS component's controller we can get hold of the * downgraded service via the name we gave when downgrading. * - * {@example upgrade/static/ts/module.ts region="example-app"} + * {@example upgrade/static/ts/full/module.ts region="example-app"} * * @param token an `InjectionToken` that identifies a service provided from Angular. * diff --git a/packages/upgrade/src/static/downgrade_module.ts b/packages/upgrade/src/static/downgrade_module.ts index dcd0d5fb79..cd9605a1e4 100644 --- a/packages/upgrade/src/static/downgrade_module.ts +++ b/packages/upgrade/src/static/downgrade_module.ts @@ -17,7 +17,86 @@ import {angular1Providers, setTempInjectorRef} from './angular1_providers'; import {NgAdapterInjector} from './util'; -/** @experimental */ +/** + * + * + * @description + * + * A helper function for creating an AngularJS module that can bootstrap an Angular module + * "on-demand" (possibly lazily) when a {@link downgradeComponent downgraded component} needs to be + * instantiated. + * + * *Part of the [upgrade/static](api?query=upgrade/static) library for hybrid upgrade apps that + * support AoT compilation.* + * + * It allows loading/bootstrapping the Angular part of a hybrid application lazily and not having to + * pay the cost up-front. For example, you can have an AngularJS application that uses Angular for + * specific routes and only instantiate the Angular modules if/when the user visits one of these + * routes. + * + * The Angular module will be bootstrapped once (when requested for the first time) and the same + * reference will be used from that point onwards. + * + * `downgradeModule()` requires either an `NgModuleFactory` or a function: + * - `NgModuleFactory`: If you pass an `NgModuleFactory`, it will be used to instantiate a module + * using `platformBrowser`'s {@link PlatformRef#bootstrapModuleFactory bootstrapModuleFactory()}. + * - `Function`: If you pass a function, it is expected to return a promise resolving to an + * `NgModuleRef`. The function is called with an array of extra {@link StaticProvider Providers} + * that are expected to be available from the returned `NgModuleRef`'s `Injector`. + * + * `downgradeModule()` returns the name of the created AngularJS wrapper module. You can use it to + * declare a dependency in your main AngularJS module. + * + * {@example upgrade/static/ts/lite/module.ts region="basic-how-to"} + * + * @usageNotes + * + * Apart from `UpgradeModule`, you can use the rest of the `upgrade/static` helpers as usual to + * build a hybrid application. Note that the Angular pieces (e.g. downgraded services) will not be + * available until the downgraded module has been bootstrapped, i.e. by instantiating a downgraded + * component. + * + *
+ * + * You cannot use `downgradeModule()` and `UpgradeModule` in the same hybrid application.
+ * Use one or the other. + * + *
+ * + * ### Differences with `UpgradeModule` + * + * Besides their different API, there are two important internal differences between + * `downgradeModule()` and `UpgradeModule` that affect the behavior of hybrid applications: + * + * 1. Unlike `UpgradeModule`, `downgradeModule()` does not bootstrap the main AngularJS module + * inside the {@link NgZone Angular zone}. + * 2. Unlike `UpgradeModule`, `downgradeModule()` does not automatically run a + * [$digest()](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest) when changes are + * detected in the Angular part of the application. + * + * What this means is that applications using `UpgradeModule` will run change detection more + * frequently in order to ensure that both frameworks are properly notified about possible changes. + * This will inevitably result in more change detection runs than necessary. + * + * `downgradeModule()`, on the other side, does not try to tie the two change detection systems as + * tightly, restricting the explicit change detection runs only to cases where it knows it is + * necessary (e.g. when the inputs of a downgraded component change). This improves performance, + * especially in change-detection-heavy applications, but leaves it up to the developer to manually + * notify each framework as needed. + * + *
+ * + * You can manually trigger a change detection run in AngularJS using + * [scope.$apply(...)](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply) or + * [$rootScope.$digest()](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest). + * + * You can manually trigger a change detection run in Angular using {@link NgZone#run + * ngZone.run(...)}. + * + *
+ * + * @experimental + */ export function downgradeModule( moduleFactoryOrBootstrapFn: NgModuleFactory| ((extraProviders: StaticProvider[]) => Promise>)): string { diff --git a/packages/upgrade/src/static/upgrade_component.ts b/packages/upgrade/src/static/upgrade_component.ts index 984067bb7a..a63699f8b4 100644 --- a/packages/upgrade/src/static/upgrade_component.ts +++ b/packages/upgrade/src/static/upgrade_component.ts @@ -42,12 +42,12 @@ class Bindings { * Let's assume that you have an AngularJS component called `ng1Hero` that needs * to be made available in Angular templates. * - * {@example upgrade/static/ts/module.ts region="ng1-hero"} + * {@example upgrade/static/ts/full/module.ts region="ng1-hero"} * * We must create a `Directive` that will make this AngularJS component * available inside Angular templates. * - * {@example upgrade/static/ts/module.ts region="ng1-hero-wrapper"} + * {@example upgrade/static/ts/full/module.ts region="ng1-hero-wrapper"} * * In this example you can see that we must derive from the `UpgradeComponent` * base class but also provide an {@link Directive `@Directive`} decorator. This is @@ -95,7 +95,7 @@ export class UpgradeComponent implements OnInit, OnChanges, DoCheck, OnDestroy { * Instead you should derive a new class from this one and call the super constructor * from the base class. * - * {@example upgrade/static/ts/module.ts region="ng1-hero-wrapper" } + * {@example upgrade/static/ts/full/module.ts region="ng1-hero-wrapper" } * * * The `name` parameter should be the name of the AngularJS directive. * * The `elementRef` and `injector` parameters should be acquired from Angular by dependency diff --git a/packages/upgrade/src/static/upgrade_module.ts b/packages/upgrade/src/static/upgrade_module.ts index 0b016d9c5c..9424b77c86 100644 --- a/packages/upgrade/src/static/upgrade_module.ts +++ b/packages/upgrade/src/static/upgrade_module.ts @@ -107,17 +107,17 @@ import {NgAdapterInjector} from './util'; * * Import the `UpgradeModule` into your top level {@link NgModule Angular `NgModule`}. * - * {@example upgrade/static/ts/module.ts region='ng2-module'} + * {@example upgrade/static/ts/full/module.ts region='ng2-module'} * * Then inject `UpgradeModule` into your Angular `NgModule` and use it to bootstrap the top level * [AngularJS module](https://docs.angularjs.org/api/ng/type/angular.Module) in the * `ngDoBootstrap()` method. * - * {@example upgrade/static/ts/module.ts region='bootstrap-ng1'} + * {@example upgrade/static/ts/full/module.ts region='bootstrap-ng1'} * * Finally, kick off the whole process, by bootstraping your top level Angular `NgModule`. * - * {@example upgrade/static/ts/module.ts region='bootstrap-ng2'} + * {@example upgrade/static/ts/full/module.ts region='bootstrap-ng2'} * * {@a upgrading-an-angular-1-service} * ### Upgrading an AngularJS service @@ -127,17 +127,17 @@ import {NgAdapterInjector} from './util'; * * Let's say you have an AngularJS service: * - * {@example upgrade/static/ts/module.ts region="ng1-title-case-service"} + * {@example upgrade/static/ts/full/module.ts region="ng1-title-case-service"} * * Then you should define an Angular provider to be included in your `NgModule` `providers` * property. * - * {@example upgrade/static/ts/module.ts region="upgrade-ng1-service"} + * {@example upgrade/static/ts/full/module.ts region="upgrade-ng1-service"} * * Then you can use the "upgraded" AngularJS service by injecting it into an Angular component * or service. * - * {@example upgrade/static/ts/module.ts region="use-ng1-upgraded-service"} + * {@example upgrade/static/ts/full/module.ts region="use-ng1-upgraded-service"} * * @experimental */