feat(core): add getNgModuleById function to retrieve loaded NgModules by id (#43580)

This commit adds a new function called `getNgModuleById` to the public API surface of the framework. The `getNgModuleById` function allows to retrieve loaded NgModule class by id (specified via `@NgModule.id`). The function is a replacement for the `getModuleFactory` function.

DEPRECATION:

The `getModuleFactory` function is deprecated in favor of the `getNgModuleById` one. With Ivy it's possible to work with NgModule classes directly, without retrieving corresponding factories, so the `getNgModuleById` should be used instead.

PR Close #43580
This commit is contained in:
Andrew Kushnir
2021-09-24 15:24:11 -07:00
committed by Dylan Hunn
parent 3d4432874c
commit fe1f6421d2
8 changed files with 57 additions and 11 deletions
@@ -44,6 +44,7 @@ export {
SWITCH_ELEMENT_REF_FACTORY__POST_R3__ as ɵSWITCH_ELEMENT_REF_FACTORY__POST_R3__,
} from './linker/element_ref';
export { getModuleFactory__POST_R3__ as ɵgetModuleFactory__POST_R3__ } from './linker/ng_module_factory_loader';
export { getNgModuleById__POST_R3__ as ɵgetNgModuleById__POST_R3__ } from './linker/ng_module_factory_loader';
export { registerNgModuleType as ɵregisterNgModuleType } from './linker/ng_module_factory_registration';
export {
SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ as ɵSWITCH_TEMPLATE_REF_FACTORY__POST_R3__,
+1 -1
View File
@@ -12,7 +12,7 @@ export {ComponentFactory, ComponentRef} from './linker/component_factory';
export {ComponentFactoryResolver} from './linker/component_factory_resolver';
export {ElementRef} from './linker/element_ref';
export {NgModuleFactory, NgModuleRef} from './linker/ng_module_factory';
export {getModuleFactory} from './linker/ng_module_factory_loader';
export {getModuleFactory, getNgModuleById} from './linker/ng_module_factory_loader';
export {QueryList} from './linker/query_list';
export {TemplateRef} from './linker/template_ref';
export {ViewContainerRef} from './linker/view_container_ref';
@@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Type} from '../interface/type';
import {NgModuleType} from '../metadata/ng_module_def';
import {NgModuleFactory as R3NgModuleFactory} from '../render3/ng_module_ref';
@@ -24,14 +26,33 @@ export function getModuleFactory__POST_R3__(id: string): NgModuleFactory<any> {
return new R3NgModuleFactory(type);
}
export function getNgModuleById__PRE_R3__(id: string): NgModuleType {
throw new Error(`ViewEngine doesn't support retrieving NgModule classes by id`);
}
export function getNgModuleById__POST_R3__(id: string): NgModuleType {
const type = getRegisteredNgModuleType<NgModuleType>(id);
if (!type) throw noModuleError(id);
return type;
}
/**
* Returns the NgModuleFactory with the given id, if it exists and has been loaded.
* Factories for modules that do not specify an `id` cannot be retrieved. Throws if the module
* cannot be found.
* Returns the NgModuleFactory with the given id (specified using [@NgModule.id
* field](api/core/NgModule#id)), if it exists and has been loaded. Factories for NgModules that do
* not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
* @publicApi
* @deprecated Use `getNgModuleById` instead.
*/
export const getModuleFactory: (id: string) => NgModuleFactory<any> = getModuleFactory__PRE_R3__;
/**
* Returns the NgModule class with the given id (specified using [@NgModule.id
* field](api/core/NgModule#id)), if it exists and has been loaded. Classes for NgModules that do
* not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
* @publicApi
*/
export const getNgModuleById: <T>(id: string) => Type<T> = getNgModuleById__PRE_R3__;
function noModuleError(
id: string,
): Error {
@@ -68,6 +68,7 @@ export function clearModulesForTest(): void {
modules.clear();
}
export function getRegisteredNgModuleType(id: string) {
return modules.get(id) || autoRegisterModuleById[id];
export function getRegisteredNgModuleType<T extends NgModuleFactory<unknown>|NgModuleType>(
id: string): T|undefined {
return (modules.get(id) || autoRegisterModuleById[id]) as T | undefined;
}
+2 -3
View File
@@ -226,9 +226,8 @@ export interface NgModule {
schemas?: Array<SchemaMetadata|any[]>;
/**
* A name or path that uniquely identifies this NgModule in `getModuleFactory`.
* If left `undefined`, the NgModule is not registered with
* `getModuleFactory`.
* A name or path that uniquely identifies this NgModule in `getNgModuleById`.
* If left `undefined`, the NgModule is not registered with `getNgModuleById`.
*/
id?: string;
@@ -6,8 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ANALYZE_FOR_ENTRY_COMPONENTS, Compiler, Component, ComponentFactoryResolver, CUSTOM_ELEMENTS_SCHEMA, Directive, forwardRef, getModuleFactory, HostBinding, Inject, Injectable, InjectionToken, Injector, Input, NgModule, NgModuleRef, Optional, Pipe, Provider, Self, Type, ɵivyEnabled as ivyEnabled, ɵɵdefineNgModule as defineNgModule} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, Compiler, Component, ComponentFactoryResolver, CUSTOM_ELEMENTS_SCHEMA, Directive, forwardRef, getModuleFactory, getNgModuleById, HostBinding, Inject, Injectable, InjectionToken, Injector, Input, NgModule, NgModuleRef, Optional, Pipe, Provider, Self, Type, ɵivyEnabled as ivyEnabled, ɵɵdefineNgModule as defineNgModule} from '@angular/core';
import {ɵɵdefineInjectable} from '@angular/core/src/di/interface/defs';
import {NgModuleType} from '@angular/core/src/render3';
import {getNgModuleDef} from '@angular/core/src/render3/definition';
import {NgModuleData} from '@angular/core/src/view/types';
import {tokenKey} from '@angular/core/src/view/util';
@@ -329,6 +330,17 @@ function declareTests(config?: {useJit: boolean}) {
class SomeModule {
}
createModule(SomeModule);
if (ivyEnabled) {
const moduleType = getNgModuleById(token);
expect(moduleType).toBeTruthy();
expect(moduleType).toBe(SomeModule as NgModuleType);
} else {
// ViewEngine doesn't support this call, expect it to throw.
expect(() => getNgModuleById(token))
.toThrowError(`ViewEngine doesn't support retrieving NgModule classes by id`);
}
const factory = getModuleFactory(token);
expect(factory).toBeTruthy();
expect(factory.moduleType).toBe(SomeModule);
@@ -377,8 +389,14 @@ function declareTests(config?: {useJit: boolean}) {
});
}
// Verify that we can retrieve NgModule factory by id.
createModuleFactory(ChildModule);
expect(getModuleFactory('child')).toBeAnInstanceOf(NgModuleFactory);
// Verify that we can also retrieve NgModule class by id.
const moduleType = getNgModuleById('child');
expect(moduleType).toBeTruthy();
expect(moduleType).toBe(ChildModule as NgModuleType);
});
});