docs(upgrade): add gotchas/tips/example for multiple downgraded modules (#27217)
PR Close #27217
This commit is contained in:
parent
077a5fb04b
commit
50a91ba28c
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* @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 {browser, by, element} from 'protractor';
|
||||
|
||||
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
|
||||
|
||||
|
||||
describe('upgrade/static (lite with multiple downgraded modules and shared root module)', () => {
|
||||
const compA = element(by.css('ng2-a'));
|
||||
const compB = element(by.css('ng2-b'));
|
||||
const compC = element(by.css('ng2-c'));
|
||||
|
||||
beforeEach(() => browser.get('/upgrade/static/ts/lite-multi-shared/'));
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
||||
it('should share the same injectable instance across downgraded modules A and B', () => {
|
||||
expect(compA.getText()).toBe('Component A (Service ID: 2)');
|
||||
expect(compB.getText()).toBe('Component B (Service ID: 2)');
|
||||
});
|
||||
|
||||
it('should use a different injectable instance on downgraded module C',
|
||||
() => { expect(compC.getText()).toBe('Component C (Service ID: 1)'); });
|
||||
});
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* @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 {Compiler, Component, Injectable, Injector, NgModule, StaticProvider, getPlatform} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
import {downgradeComponent, downgradeModule} from '@angular/upgrade/static';
|
||||
|
||||
|
||||
declare var angular: ng.IAngularStatic;
|
||||
|
||||
// An Angular service provided in root. Each instance of the service will get a new ID.
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class Ng2Service {
|
||||
static nextId = 1;
|
||||
id = Ng2Service.nextId++;
|
||||
}
|
||||
|
||||
|
||||
// An Angular module that will act as "root" for all downgraded modules, so that injectables
|
||||
// provided in root will be available to all.
|
||||
@NgModule({
|
||||
imports: [BrowserModule],
|
||||
})
|
||||
export class Ng2RootModule {
|
||||
ngDoBootstrap() {}
|
||||
}
|
||||
|
||||
|
||||
// An Angular module that declares an Angular component,
|
||||
// which in turn uses an Angular service from the root module.
|
||||
@Component({
|
||||
selector: 'ng2A',
|
||||
template: 'Component A (Service ID: {{ service.id }})',
|
||||
})
|
||||
export class Ng2AComponent {
|
||||
constructor(public service: Ng2Service) {}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [Ng2AComponent],
|
||||
entryComponents: [Ng2AComponent],
|
||||
})
|
||||
export class Ng2AModule {
|
||||
ngDoBootstrap() {}
|
||||
}
|
||||
|
||||
|
||||
// Another Angular module that declares an Angular component, which uses the same service.
|
||||
@Component({
|
||||
selector: 'ng2B',
|
||||
template: 'Component B (Service ID: {{ service.id }})',
|
||||
})
|
||||
export class Ng2BComponent {
|
||||
constructor(public service: Ng2Service) {}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [Ng2BComponent],
|
||||
entryComponents: [Ng2BComponent],
|
||||
})
|
||||
export class Ng2BModule {
|
||||
ngDoBootstrap() {}
|
||||
}
|
||||
|
||||
|
||||
// A third Angular module that declares an Angular component, which uses the same service.
|
||||
@Component({
|
||||
selector: 'ng2C',
|
||||
template: 'Component C (Service ID: {{ service.id }})',
|
||||
})
|
||||
export class Ng2CComponent {
|
||||
constructor(public service: Ng2Service) {}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [BrowserModule],
|
||||
declarations: [Ng2CComponent],
|
||||
entryComponents: [Ng2CComponent],
|
||||
})
|
||||
export class Ng2CModule {
|
||||
ngDoBootstrap() {}
|
||||
}
|
||||
|
||||
|
||||
// The downgraded Angular modules. Modules A and B share a common root module. Module C does not.
|
||||
// #docregion shared-root-module
|
||||
let rootInjectorPromise: Promise<Injector>|null = null;
|
||||
const getRootInjector = (extraProviders: StaticProvider[]) => {
|
||||
if (!rootInjectorPromise) {
|
||||
rootInjectorPromise = platformBrowserDynamic(extraProviders)
|
||||
.bootstrapModule(Ng2RootModule)
|
||||
.then(moduleRef => moduleRef.injector);
|
||||
}
|
||||
return rootInjectorPromise;
|
||||
};
|
||||
|
||||
const downgradedNg2AModule = downgradeModule(async(extraProviders: StaticProvider[]) => {
|
||||
const rootInjector = await getRootInjector(extraProviders);
|
||||
const moduleAFactory = await rootInjector.get(Compiler).compileModuleAsync(Ng2AModule);
|
||||
return moduleAFactory.create(rootInjector);
|
||||
});
|
||||
const downgradedNg2BModule = downgradeModule(async(extraProviders: StaticProvider[]) => {
|
||||
const rootInjector = await getRootInjector(extraProviders);
|
||||
const moduleBFactory = await rootInjector.get(Compiler).compileModuleAsync(Ng2BModule);
|
||||
return moduleBFactory.create(rootInjector);
|
||||
});
|
||||
// #enddocregion shared-root-module
|
||||
|
||||
const downgradedNg2CModule = downgradeModule(
|
||||
(extraProviders: StaticProvider[]) =>
|
||||
(getPlatform() || platformBrowserDynamic(extraProviders)).bootstrapModule(Ng2CModule));
|
||||
|
||||
|
||||
// The AngularJS app including downgraded modules and components.
|
||||
// #docregion shared-root-module
|
||||
const appModule =
|
||||
angular
|
||||
.module(
|
||||
'exampleAppModule', [downgradedNg2AModule, downgradedNg2BModule, downgradedNg2CModule])
|
||||
// #enddocregion shared-root-module
|
||||
.component('exampleApp', {template: '<ng2-a></ng2-a> | <ng2-b></ng2-b> | <ng2-c></ng2-c>'})
|
||||
.directive('ng2A', downgradeComponent({
|
||||
component: Ng2AComponent,
|
||||
// Since there is more than one downgraded Angular module,
|
||||
// specify which module this component belongs to.
|
||||
downgradedModule: downgradedNg2AModule,
|
||||
propagateDigest: false,
|
||||
}))
|
||||
.directive('ng2B', downgradeComponent({
|
||||
component: Ng2BComponent,
|
||||
// Since there is more than one downgraded Angular module,
|
||||
// specify which module this component belongs to.
|
||||
downgradedModule: downgradedNg2BModule,
|
||||
propagateDigest: false,
|
||||
}))
|
||||
.directive('ng2C', downgradeComponent({
|
||||
component: Ng2CComponent,
|
||||
// Since there is more than one downgraded Angular module,
|
||||
// specify which module this component belongs to.
|
||||
downgradedModule: downgradedNg2CModule,
|
||||
propagateDigest: false,
|
||||
}));
|
||||
|
||||
|
||||
// Bootstrap the AngularJS app.
|
||||
angular.bootstrap(document.body, [appModule.name]);
|
|
@ -103,14 +103,14 @@ const appModule =
|
|||
})
|
||||
.directive('ng2A', downgradeComponent({
|
||||
component: Ng2AComponent,
|
||||
// Since there are more than one downgraded Angular module,
|
||||
// Since there is more than one downgraded Angular module,
|
||||
// specify which module this component belongs to.
|
||||
downgradedModule: downgradedNg2AModule,
|
||||
propagateDigest: false,
|
||||
}))
|
||||
.directive('ng2B', downgradeComponent({
|
||||
component: Ng2BComponent,
|
||||
// Since there are more than one downgraded Angular module,
|
||||
// Since there is more than one downgraded Angular module,
|
||||
// specify which module this component belongs to.
|
||||
downgradedModule: downgradedNg2BModule,
|
||||
propagateDigest: false,
|
||||
|
|
|
@ -101,6 +101,31 @@ let moduleUid = 0;
|
|||
*
|
||||
* </div>
|
||||
*
|
||||
* ### Downgrading multiple modules
|
||||
*
|
||||
* It is possible to downgrade multiple modules and include them in an AngularJS application. In
|
||||
* that case, each downgraded module will be bootstrapped when an associated downgraded component or
|
||||
* injectable needs to be instantiated.
|
||||
*
|
||||
* Things to keep in mind, when downgrading multiple modules:
|
||||
*
|
||||
* - Each downgraded component/injectable needs to be explicitly associated with a downgraded
|
||||
* module. See `downgradeComponent()` and `downgradeInjectable()` for more details.
|
||||
*
|
||||
* - If you want some injectables to be shared among all downgraded modules, you can provide them as
|
||||
* `StaticProvider`s, when creating the `PlatformRef` (e.g. via `platformBrowser` or
|
||||
* `platformBrowserDynamic`).
|
||||
*
|
||||
* - When using {@link PlatformRef#bootstrapmodule `bootstrapModule()`} or
|
||||
* {@link PlatformRef#bootstrapmodulefactory `bootstrapModuleFactory()`} to bootstrap the
|
||||
* downgraded modules, each one is considered a "root" module. As a consequence, a new instance
|
||||
* will be created for every injectable provided in `"root"` (via
|
||||
* {@link Injectable#providedIn `providedIn`}).
|
||||
* If this is not your intention, you can have a shared module (that will act as act as the "root"
|
||||
* module) and create all downgraded modules using that module's injector:
|
||||
*
|
||||
* {@example upgrade/static/ts/lite-multi-shared/module.ts region="shared-root-module"}
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function downgradeModule<T>(
|
||||
|
|
Loading…
Reference in New Issue