|
| 1 | +# NgModules |
| 2 | + |
| 3 | +IMPORTANT: The Angular team recommends using [standalone components](guide/components/anatomy-of-components#-imports-in-the-component-decorator) instead of `NgModule` for all new code. Use this guide to understand existing code built with `@NgModule`. |
| 4 | + |
| 5 | +An NgModule is a class marked by the `@NgModule` decorator. This decorator accepts _metadata_ that tells Angular how to compile component templates and configure dependency injection. |
| 6 | + |
| 7 | +```typescript |
| 8 | +import {NgModule} from '@angular/core'; |
| 9 | + |
| 10 | +@NgModule({ |
| 11 | + // Metadata goes here |
| 12 | +}) |
| 13 | +export class CustomMenuModule { } |
| 14 | +``` |
| 15 | + |
| 16 | +An NgModule has two main responsibilities: |
| 17 | + |
| 18 | +- Declaring components, directives, and pipes that belong to the NgModule |
| 19 | +- Add providers to the injector for components, directives, and pipes that import the NgModule |
| 20 | + |
| 21 | +## Declarations |
| 22 | + |
| 23 | +The `declarations` property of the `@NgModule` metadata declares the components, directives, and pipes that belong to the NgModule. |
| 24 | + |
| 25 | +```typescript |
| 26 | +@NgModule({ |
| 27 | + /* ... */ |
| 28 | + // CustomMenu and CustomMenuItem are components. |
| 29 | + declarations: [CustomMenu, CustomMenuItem], |
| 30 | +}) |
| 31 | +export class CustomMenuModule { } |
| 32 | +``` |
| 33 | + |
| 34 | +In the example above, the components `CustomMenu` and `CustomMenuItem` belong to `CustomMenuModule`. |
| 35 | + |
| 36 | +The `declarations` property additionally accepts _arrays_ of components, directives, and pipes. These arrays, in turn, may also contain other arrays. |
| 37 | + |
| 38 | +```typescript |
| 39 | +const MENU_COMPONENTS = [CustomMenu, CustomMenuItem]; |
| 40 | +const WIDGETS = [MENU_COMPONENTS, CustomSlider]; |
| 41 | + |
| 42 | +@NgModule({ |
| 43 | + /* ... */ |
| 44 | + // This NgModule declares all of CustomMenu, CustomMenuItem, |
| 45 | + // CustomSlider, and CustomCheckbox. |
| 46 | + declarations: [WIDGETS, CustomCheckbox], |
| 47 | +}) |
| 48 | +export class CustomMenuModule { } |
| 49 | +``` |
| 50 | + |
| 51 | +If Angular discovers any components, directives, or pipes declared in more than one NgModule, it reports an error. |
| 52 | + |
| 53 | +Any components, directives, or pipes must be explicitly marked as `standalone: false` in order to be declared in an NgModule. |
| 54 | + |
| 55 | +```typescript |
| 56 | +@Component({ |
| 57 | + // Mark this component as `standalone: false` so that it can be declared in an NgModule. |
| 58 | + standalone: false, |
| 59 | + /* ... */ |
| 60 | +}) |
| 61 | +export class CustomMenu { /* ... */ } |
| 62 | +``` |
| 63 | + |
| 64 | +### imports |
| 65 | + |
| 66 | +Components declared in an NgModule may depend on other components, directives, and pipes. Add these dependencies to the `imports` property of the `@NgModule` metadata. |
| 67 | + |
| 68 | +```typescript |
| 69 | +@NgModule({ |
| 70 | + /* ... */ |
| 71 | + // CustomMenu and CustomMenuItem depend on the PopupTrigger and SelectorIndicator components. |
| 72 | + imports: [PopupTrigger, SelectionIndicator], |
| 73 | + declarations: [CustomMenu, CustomMenuItem], |
| 74 | +}) |
| 75 | +export class CustomMenuModule { } |
| 76 | +``` |
| 77 | + |
| 78 | +The `imports` array accepts other NgModules, as well as standalone components, directives, and pipes. |
| 79 | + |
| 80 | +### exports |
| 81 | + |
| 82 | +An NgModule can _export_ its declared components, directives, and pipes such that they're available to other components and NgModules. |
| 83 | + |
| 84 | +```typescript |
| 85 | +@NgModule({ |
| 86 | + imports: [PopupTrigger, SelectionIndicator], |
| 87 | + declarations: [CustomMenu, CustomMenuItem], |
| 88 | + |
| 89 | + // Make CustomMenu and CustomMenuItem available to |
| 90 | + // components and NgModules that import CustomMenuModule. |
| 91 | + exports: [CustomMenu, CustomMenuItem], |
| 92 | +}) |
| 93 | +export class CustomMenuModule { } |
| 94 | +``` |
| 95 | + |
| 96 | +The `exports` property is not limited to declarations, however. An NgModule can also export any other components, directives, pipes, and NgModules that it imports. |
| 97 | + |
| 98 | +```typescript |
| 99 | +@NgModule({ |
| 100 | + imports: [PopupTrigger, SelectionIndicator], |
| 101 | + declarations: [CustomMenu, CustomMenuItem], |
| 102 | + |
| 103 | + // Also make PopupTrigger available to any component or NgModule that imports CustomMenuModule. |
| 104 | + exports: [CustomMenu, CustomMenuItem, PopupTrigger], |
| 105 | +}) |
| 106 | +export class CustomMenuModule { } |
| 107 | +``` |
| 108 | + |
| 109 | +## `NgModule` providers |
| 110 | + |
| 111 | +TIP: See the [Dependency Injection guide](guide/di) for information on dependency injection and providers. |
| 112 | + |
| 113 | +An `NgModule` can specify `providers` for injected dependencies. These providers are available to: |
| 114 | + |
| 115 | +- Any standalone component, directive, or pipe that imports the NgModule, and |
| 116 | +- The `declarations` and `providers` of any _other_ NgModule that imports the NgModule. |
| 117 | + |
| 118 | +```typescript |
| 119 | +@NgModule({ |
| 120 | + imports: [PopupTrigger, SelectionIndicator], |
| 121 | + declarations: [CustomMenu, CustomMenuItem], |
| 122 | + |
| 123 | + // Provide the OverlayManager service |
| 124 | + providers: [OverlayManager], |
| 125 | + /* ... */ |
| 126 | +}) |
| 127 | +export class CustomMenuModule { } |
| 128 | + |
| 129 | +@NgModule({ |
| 130 | + imports: [CustomMenuModule], |
| 131 | + declarations: [UserProfile], |
| 132 | + providers: [UserDataClient], |
| 133 | +}) |
| 134 | +export class UserProfileModule { } |
| 135 | +``` |
| 136 | + |
| 137 | +In the example above: |
| 138 | + |
| 139 | +- The `CustomMenuModule` provides `OverlayManager`. |
| 140 | +- The `CustomMenu` and `CustomMenuItem` components can inject `OverlayManager` because they're declared in `CustomMenuModule`. |
| 141 | +- `UserProfile` can inject `OverlayManager` because its NgModule imports `CustomMenuModule`. |
| 142 | +- `UserDataClient` can inject `OverlayManager` because its NgModule imports `CustomMenuModule`. |
| 143 | + |
| 144 | +### The `forRoot` and `forChild` pattern |
| 145 | + |
| 146 | +Some NgModules define a static `forRoot` method that accepts some configuration and returns an array of providers. The name "`forRoot`" is a convention that indicates that these providers are intended to be added exclusively to the _root_ of your application during bootstrap. |
| 147 | + |
| 148 | +Any providers included in this way are eagerly loaded, increasing the JavaScript bundle size of your initial page load. |
| 149 | + |
| 150 | +```typescript |
| 151 | +bootstrapApplication(MyApplicationRoot, { |
| 152 | + providers: [ |
| 153 | + CustomMenuModule.forRoot(/* some config */), |
| 154 | + ], |
| 155 | +}); |
| 156 | +``` |
| 157 | + |
| 158 | +Similarly, some NgModules may define a static `forChild` that indicates the providers are intended to be added to components within your application hierarchy. |
| 159 | + |
| 160 | +```typescript |
| 161 | +@Component({ |
| 162 | + /* ... */ |
| 163 | + providers: [ |
| 164 | + CustomMenuModule.forChild(/* some config */), |
| 165 | + ], |
| 166 | +}) |
| 167 | +export class UserProfile { /* ... */ } |
| 168 | +``` |
| 169 | + |
| 170 | +## Bootstrapping an application |
| 171 | + |
| 172 | +IMPORTANT: The Angular team recommends using [bootstrapApplication](api/platform-browser/bootstrapApplication) instead of `bootstrapModule` for all new code. Use this guide to understand existing applications bootstrapped with `@NgModule`. |
| 173 | + |
| 174 | +The `@NgModule` decorator accepts an optional `bootstrap` array that may contain one or more components. |
| 175 | + |
| 176 | +You can use the [`bootstrapModule`](https://angular.dev/api/core/PlatformRef#bootstrapModule) method from either [`platformBrowser`](api/platform-browser/platformBrowser) or [`platformServer`](api/platform-server/platformServer) to start an Angular application. When run, this function locates any elements on the page with a CSS selector that matches the listed componet(s) and renders those components on the page. |
| 177 | + |
| 178 | +```typescript |
| 179 | +import {platformBrowser} from '@angular/platform-browser'; |
| 180 | + |
| 181 | +@NgModule({ |
| 182 | + bootstrap: [MyApplication], |
| 183 | +}) |
| 184 | +export class MyApplicationModule { } |
| 185 | + |
| 186 | +platformBrowser().bootstrapModule(MyApplicationModule); |
| 187 | +``` |
| 188 | + |
| 189 | +Components listed in `bootstrap` are automatically included in the NgModule's declarations. |
| 190 | + |
| 191 | +When you bootstrap an application from an NgModule, the collected `providers` of this module and all of the `providers` of its `imports` are eagerly loaded and available to inject for the entire application. |
0 commit comments