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
*/