What is the difference between declarations, providers, and import in NgModule?
Asked Answered
D

6

530

I am trying to understand Angular (sometimes called Angular2+), then I came across @Module:

  1. Imports

  2. Declarations

  3. Providers

Following Angular Quick Start

Directional answered 21/8, 2016 at 9:51 Comment(0)
C
651

Angular Concepts

  • imports makes the exported declarations of other modules available in the current module
  • declarations are to make directives (including components and pipes) from the current module available to other directives in the current module. Selectors of directives, components or pipes are only matched against the HTML if they are declared or imported.
  • providers are to make services and values known to DI (dependency injection). They are added to the root scope and they are injected to other services or directives that have them as dependency.

A special case for providers are lazy loaded modules that get their own child injector. providers of a lazy loaded module are only provided to this lazy loaded module by default (not the whole application as it is with other modules).

For more details about modules see also https://angular.io/docs/ts/latest/guide/ngmodule.html

  • exports makes the components, directives, and pipes available in modules that add this module to imports. exports can also be used to re-export modules such as CommonModule and FormsModule, which is often done in shared modules.

  • entryComponents registers components for offline compilation so that they can be used with ViewContainerRef.createComponent(). Components used in router configurations are added implicitly.

TypeScript (ES2015) imports

import ... from 'foo/bar' (which may resolve to an index.ts) are for TypeScript imports. You need these whenever you use an identifier in a typescript file that is declared in another typescript file.

Angular's @NgModule() imports and TypeScript import are entirely different concepts.

See also jDriven - TypeScript and ES6 import syntax

Most of them are actually plain ECMAScript 2015 (ES6) module syntax that TypeScript uses as well.

Chimere answered 21/8, 2016 at 10:33 Comment(9)
I think, but I'm not sure, that the latest recommendation is to put app-wide providers in a CoreModule, rather than using forRoot() in a lazy-loaded module. Do you agree? See The Core Module. The link to #shared-module-for-root no longer exists.Wishful
Excellent explanation. Thank you, @günter-zöchbauer. Only mention is that afaik import is a JS (ES2015) functionality, not a TypeScript one. :)Hoecake
and what is export [] in NgModule suck like export : [MatCheckBox]Shortfall
Identifiers listed in export: [...] become available to modules that list the exporting module in imports: [SomeModule]. All other directives, components, and pipes are private to the module until they are exported. Actually my answer above says that already :DPromethean
To be honest, I think the design of NgModule of Angular is clumsy and obscure comparing with Vue and React. You needs import other module with imports, but export your declarables (component, directive, pipe) with exports. So, the major targets of imports and exports is different things. Instead, the major target of exports is your declarations. You declare your component by declarations, but for dynamic loaded component, you need put them in entryComponents. In the meantime, the providers are managed in another story by DI.Pretrice
a convoluted answer describing a convoluted frameworkMethodism
Gunter, I'm missing the boat here: "A special case for providers are lazy loaded modules that get their own child injector. providers of a lazy loaded module are only provided to this lazy loaded module by default (not the whole application as it is with other modules)." The 2nd sentence seems circular -- maybe it's me being new to Angular but I read this many times, coming away with "What the heck did Gunter just say ... "Necropolis
Only so many characters can be added, so reference the above comment please -- providers only provide DI metadata to the current component, right? That's what providers do -- provide DI metadata so that services are available by DI, yes? Where is it said this done globally? Newbie here, OK? Thanks!Necropolis
Let the 5 minute edit deadline pass ... We have a shared module used by 3 other classes. Are you saying lazy loaded providers won't be available to inheriting classes? Is this the point?Necropolis
R
136

imports are used to import supporting modules like FormsModule, RouterModule, CommonModule, or any other custom-made feature module.

declarations are used to declare components, directives, pipes that belong to the current module. Everyone inside declarations knows each other. For example, if we have a component, say UsernameComponent, which displays a list of the usernames and we also have a pipe, say toupperPipe, which transforms a string to an uppercase letter string. Now If we want to show usernames in uppercase letters in our UsernameComponent then we can use the toupperPipe which we had created before but the question is how UsernameComponent knows that the toupperPipe exists and how it can access and use that. Here come the declarations, we can declare UsernameComponent and toupperPipe.

Providers are used for injecting the services required by components, directives, pipes in the module.

Readability answered 21/8, 2016 at 10:43 Comment(1)
"declarations: is used to declare components, directives, pipes that belongs to the current module. Everything inside declarations knows each other." this should be the accepted answerPecksniffian
H
102

Components are declared, Modules are imported, and Services are provided. An example I'm working with:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


import { AppComponent } from './app.component';
import {FormsModule} from '@angular/forms';
import { UserComponent } from './components/user/user.component';
import { StateService } from './services/state.service';    

@NgModule({
  declarations: [
    AppComponent,
    UserComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [ StateService ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
Hamamatsu answered 15/1, 2018 at 10:48 Comment(3)
I like the simplicity of this explanation, but it leaves me wondering why there isn't just one "stuffsThisComponentNeeds" property? Seems like they all are dealing with the same thing, which is making other pieces of code available to the current component.Allowedly
@Allowedly I agree. In Node.js for example, everything is imported the same way regardless of whether it is a DB Model,module,service or installed 3rd party package. And I think same happens with reactJSHamamatsu
I agree as well. It seems like essentially it's all importing so you can use and reference those things. In C# there are only import statements, no declarations, import array or providers. And if you already have an import statement, why have an imports array? Seems like doing the same thing twice.Gherlein
B
44

Adding a quick cheat sheet that may help after the long break with Angular:


DECLARATIONS

Example:

declarations: [AppComponent]

What can we inject here? Components, pipes, directives


IMPORTS

Example:

imports: [BrowserModule, AppRoutingModule]

What can we inject here? other modules


PROVIDERS

Example:

providers: [UserService]

What can we inject here? services


BOOTSTRAP

Example:

bootstrap: [AppComponent]

What can we inject here? the main component that will be generated by this module (top parent node for a component tree)


ENTRY COMPONENTS

Example:

entryComponents: [PopupComponent]

What can we inject here? dynamically generated components (for instance by using ViewContainerRef.createComponent())


EXPORT

Example:

export: [TextDirective, PopupComponent, BrowserModule]

What can we inject here? components, directives, modules or pipes that we would like to have access to them in another module (after importing this module)

Basso answered 3/9, 2019 at 13:56 Comment(4)
What about export?Flatboat
@Flatboat I've added export into this listSantiago
I love this layout for the explanation, very digestible. Thanks!Reisinger
FYI, Entry Components are now deprecated. angular.io/guide/…Doglike
M
21

Angular @NgModule constructs:

  1. import { x } from 'y';: This is standard typescript syntax (ES2015/ES6 module syntax) for importing code from other files. This is not Angular specific. Also this is technically not part of the module, it is just necessary to get the needed code within scope of this file.
  2. imports: [FormsModule]: You import other modules in here. For example we import FormsModule in the example below. Now we can use the functionality which the FormsModule has to offer throughout this module.
  3. declarations: [OnlineHeaderComponent, ReCaptcha2Directive]: You put your components, directives, and pipes here. Once declared here you now can use them throughout the whole module. For example we can now use the OnlineHeaderComponent in the AppComponent view (html file). Angular knows where to find this OnlineHeaderComponent because it is declared in the @NgModule.
  4. providers: [RegisterService]: Here our services of this specific module are defined. You can use the services in your components by injecting with dependency injection.

Example module:

// Angular
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

// Components
import { AppComponent } from './app.component';
import { OfflineHeaderComponent } from './offline/offline-header/offline-header.component';
import { OnlineHeaderComponent } from './online/online-header/online-header.component';

// Services
import { RegisterService } from './services/register.service';

// Directives
import { ReCaptcha2Directive } from './directives/re-captcha2.directive';

@NgModule({
  declarations: [
    OfflineHeaderComponent,,
    OnlineHeaderComponent,
    ReCaptcha2Directive,
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
  ],
  providers: [
    RegisterService,
  ],
  entryComponents: [
    ChangePasswordComponent,
    TestamentComponent,
    FriendsListComponent,
    TravelConfirmComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
Meg answered 15/10, 2018 at 17:14 Comment(0)
L
12
  1. declarations: This property tells about the Components, Directives and Pipes that belong to this module.
  2. exports: The subset of declarations that should be visible and usable in the component templates of other NgModules.
  3. imports: Other modules whose exported classes are needed by component templates declared in this NgModule.
  4. providers: Creators of services that this NgModule contributes to the global collection of services; they become accessible in all parts of the app. (You can also specify providers at the component level, which is often preferred.)
  5. bootstrap: The main application view, called the root component, which hosts all other app views. Only the root NgModule should set the bootstrap property.
Lindo answered 31/12, 2019 at 6:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.