diff --git a/aio/content/guide/deprecations.md b/aio/content/guide/deprecations.md
index d6aadfdf03e..ce6e65ea2c6 100644
--- a/aio/content/guide/deprecations.md
+++ b/aio/content/guide/deprecations.md
@@ -30,6 +30,7 @@ v9 - v12
v10 - v13
v11 - v14
v12 - v15
+v13 -> v16
-->
| Area | API or Feature | May be removed in |
@@ -42,6 +43,7 @@ v12 - v15
| `@angular/core` | [`RenderComponentType`](#core) | v11 |
| `@angular/core` | [Factory-based signature of `ApplicationRef.bootstrap`](#core) | v15 |
| `@angular/core` | [`PlatformRef.bootstrapModuleFactory`](#core) | v15 |
+| `@angular/core` | [`getModuleFactory`](#core) | v16 |
| `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | v11 |
| `@angular/upgrade` | [`@angular/upgrade`](#upgrade) | v11 |
| `@angular/upgrade` | [`getAngularLib`](#upgrade-static) | v11 |
@@ -105,6 +107,7 @@ This section contains a complete list all of the currently-deprecated APIs, with
| [`entryComponents`](api/core/NgModule#entryComponents) | none | v9 | See [`entryComponents`](#entryComponents) |
| [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | v9 | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](#entryComponents) |
| [`async`](api/core/testing/async) | [`waitForAsync`](api/core/testing/waitForAsync) | v11 | The [`async`](api/core/testing/async) function from `@angular/core/testing` has been renamed to `waitForAsync` in order to avoid confusion with the native JavaScript async syntax. The existing function is deprecated and will be removed in a future version. |
+| [`getModuleFactory`](api/core/getModuleFactory) | [`getNgModuleById`](api/core/getNgModuleById) | v13 | Ivy allows working with NgModule classes directly, without retrieving corresponding factories. |
| `ViewChildren.emitDistinctChangesOnly` / `ContentChildren.emitDistinctChangesOnly` | none (was part of [issue #40091](https://github.com/angular/angular/issues/40091)) | | This is a temporary flag introduced as part of bugfix of [issue #40091](https://github.com/angular/angular/issues/40091) and will be removed. |
| Factory-based signature of [`ApplicationRef.bootstrap`](api/core/ApplicationRef#bootstrap) | Type-based signature of [`ApplicationRef.bootstrap`](api/core/ApplicationRef#bootstrap) | v13 | With Ivy, there is no need to resolve Component factory and Component Type can be provided directly. |
| [`PlatformRef.bootstrapModuleFactory`](api/core/PlatformRef#bootstrapModuleFactory) | [`PlatformRef.bootstrapModule`](api/core/PlatformRef#bootstrapModule) | v13 | With Ivy, there is no need to resolve NgModule factory and NgModule Type can be provided directly. |
diff --git a/goldens/public-api/core/core.md b/goldens/public-api/core/core.md
index 1c20508fc8e..7c498a4abe7 100644
--- a/goldens/public-api/core/core.md
+++ b/goldens/public-api/core/core.md
@@ -496,9 +496,12 @@ export interface ForwardRefFn {
// @public (undocumented)
export const getDebugNode: (nativeNode: any) => DebugNode | null;
-// @public
+// @public @deprecated
export const getModuleFactory: (id: string) => NgModuleFactory;
+// @public
+export const getNgModuleById: (id: string) => Type;
+
// @public
export function getPlatform(): PlatformRef | null;
diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts
index 4283ecdb179..cbdad67b2bf 100644
--- a/packages/core/src/core_render3_private_export.ts
+++ b/packages/core/src/core_render3_private_export.ts
@@ -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__,
diff --git a/packages/core/src/linker.ts b/packages/core/src/linker.ts
index d923e7af91b..8b0cd8a861a 100644
--- a/packages/core/src/linker.ts
+++ b/packages/core/src/linker.ts
@@ -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';
diff --git a/packages/core/src/linker/ng_module_factory_loader.ts b/packages/core/src/linker/ng_module_factory_loader.ts
index 44a5a3ec404..ed48139747b 100644
--- a/packages/core/src/linker/ng_module_factory_loader.ts
+++ b/packages/core/src/linker/ng_module_factory_loader.ts
@@ -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 {
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(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 = 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: (id: string) => Type = getNgModuleById__PRE_R3__;
+
function noModuleError(
id: string,
): Error {
diff --git a/packages/core/src/linker/ng_module_factory_registration.ts b/packages/core/src/linker/ng_module_factory_registration.ts
index 2462d86b1bc..dcfe5a38e97 100644
--- a/packages/core/src/linker/ng_module_factory_registration.ts
+++ b/packages/core/src/linker/ng_module_factory_registration.ts
@@ -68,6 +68,7 @@ export function clearModulesForTest(): void {
modules.clear();
}
-export function getRegisteredNgModuleType(id: string) {
- return modules.get(id) || autoRegisterModuleById[id];
+export function getRegisteredNgModuleType|NgModuleType>(
+ id: string): T|undefined {
+ return (modules.get(id) || autoRegisterModuleById[id]) as T | undefined;
}
diff --git a/packages/core/src/metadata/ng_module.ts b/packages/core/src/metadata/ng_module.ts
index acbd2000d34..43b4a1c0fff 100644
--- a/packages/core/src/metadata/ng_module.ts
+++ b/packages/core/src/metadata/ng_module.ts
@@ -226,9 +226,8 @@ export interface NgModule {
schemas?: Array;
/**
- * 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;
diff --git a/packages/core/test/linker/ng_module_integration_spec.ts b/packages/core/test/linker/ng_module_integration_spec.ts
index e5f2b36329b..0a736f60aca 100644
--- a/packages/core/test/linker/ng_module_integration_spec.ts
+++ b/packages/core/test/linker/ng_module_integration_spec.ts
@@ -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);
});
});