Note Translation: To understand this article, you must have basic knowledge of Angular: what are components, how to create a simple SPA application, etc. If you are not familiar with this topic, then I recommend first to get acquainted with the example of creating a SPA application from the office. documentation.
@NgModule
is a decorator added to Angular 2. From the official documentation, it follows that @NgModule
defines a class as an Angular module. Angular modules help break an application into parts (modules) that interact with each other and ultimately represent a holistic application. In other words, a module is a package or encapsulation of a part of the application functional. Modules can be designed for reuse, i.e. independent of the specific implementation of the application.
Please note that if you want to implement lazy load in your application, then you need to use the concept of Angular Modules when designing the application.
The root module in the Angular application is used as an entry point. A module is a class that is decorated with @NgModule
. Take a look at the standard module code (for example, when creating a new project via ng new project-name
, the following AppModule
is AppModule
:
// app.module.ts @NgModule({ imports: [BrowserModule], declarations: [AppComponent], bootstrap: [AppComponent], }) export class AppModule { }
A javascript object is used as an argument in the @NgModule
decorator.
In the declarations
property, we declare the components that our module contains. In this case, this is the AppComponent
component. There may be several components, they are declared separated by commas (as in a regular JavaScript array).
declarations: [AppComponent]
Suppose our component has a selector my-app
. When we write a <my-app></my-app>
application in the HTML template, the application loads the component.
How does a component load into the DOM?
AppModule
tells the browser to build the AppComponent
component into the DOM.
How does the AppModule
add a component to the DOM?
AppModule
imports Angular service modules, for exampleBrowserModule
, responsible for the application in the browser. In essence, this is a service that interacts with our code (for example, AppComponent
) and the browser API. BrowserModule
also includes NgIf
and NgFor
, which we can use in component templates.
AppModule
acts as a AppModule
between the data, its presentation and the browser.
Using the Angular application begins with the main.ts
file, read the manual for details.
// main.ts import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);
In the example above, we use dynamic compilation (JIT - Just In Time) . However, in Angular, you can implement AOT-compilation (Ahead of Time) , but this is an extensive topic and will be discussed in another article.
In our applications we create our own components, directives and pipes. We can tell our application what functionality we want to add (components, directives and pipes) by listing them in the declarations
property of the object, which is an argument for the @NgModule
decorator:
// app.module.ts @NgModule({ imports: [BrowserModule], declarations: [ AppComponent, VehicleListComponent, VehicleSelectionDirective, VehicleSortingPipe ], bootstrap: [AppComponent], }) export class AppModule { }
After declaring components, we can use them inside other components through their selector, which is indicated in the component description.
We import the BrowserModule
into AppModule
, which in turn imports the CommonModule
, which contains the NgIf
and NgFor
that are available in Angular from the box. CommonModule
importing CommonModule
we get access to the functionality implemented in this module throughout the application.
But what if we want to use the functionality that is needed to implement forms, such as ngModel
and http
? The solution is simple - we just need to import these modules into the AppModule
:
// app.module.ts @NgModule({ imports: [ BrowserModule, FormsModule, HttpModule ], declarations: [ AppComponent, VehicleListComponent, VehicleSelectionDirective, VehicleSortingPipe ], bootstrap: [AppComponent], }) export class AppModule { }
After we imported the FormsModule
module, we can use ngModel
in the templates of our components. And the HttpModule
allows us to send or receive data via the HTTP protocol.
Often in our applications there are services that we want to use in several (or all) components. How to provide all components access to the service? Use Angular Modules.
To do this, you need to add the provider to the root module, in our case AppModule
. In Angular, adding dependencies is implemented using the Dependency Incetion pattern. When we added the provider to the root module AppModule
, it will be available in any part of the application.
As the most illustrative example of a provider that is needed in our application everywhere is the authorization service (Logger Service). Our application should also show the list of active users, so we need VehicleService
to retrieve the list of active users by accessing the API using http
, which we can use thanks to the HttpModule
module. We imported it into our application earlier.
// logger.service.ts import { Injectable } from '@angular/core'; @Injectable() export class LoggerService { log = (msg: string) => { console.log(msg); }; }
// vehicle.service.ts import { Injectable } from '@angular/core'; @Injectable() export class VehicleService { getVehicles = () => [ { id: 1, name: 'X-Wing Fighter' }, { id: 2, name: 'Tie Fighter' }, { id: 3, name: 'Y-Wing Fighter' } ]; }
When we presented these services in the root module AppModule
they are available in the application components:
// app.module.ts @NgModule({ imports: [BrowserModule, FormsModule, HttpModule], declarations: [ AppComponent, VehicleListComponent, VehicleSelectionDirective, VehicleSortingPipe ], providers: [ LoggerService, VehicleService, UserProfileService ], bootstrap: [AppComponent], }) export class AppModule { }
We describe how this works. We added the creation of a provider object to our component constructor, it looks like this:
// some.component.ts @Component({ selector: 'some-component', template: '<h1>Some component {{ service.data }}</h1>' styleUrls: ['./path/to/style.css'] }) export class SomeComponent implements OnInit{ construcotr (private service: Service){} // // }
When creating an instance of a component (for example, when we opened the page where the component is used), a service object is created simultaneously, described in the providers
property (see listing app.module.ts above) and Angular starts looking for the class of this service in the parent components. Since we did not declare the provider in the components, eventually Angular will find this service in the root module of AppModule
. It should be noted that the provider in Angular implements the Singleton pattern, so that only one instance of the service class can be created in the application. In our case, if the service instance has already been created somewhere, then the component will use it, if not, it will create a service object.
Providers, in my opinion, are one of the most interesting and complex concepts of the Angular modular system. The basic rule of using providers (services) is to create an instance of the service in the root module and transfer this instance to other parts (components) of the application on request.
- Telegram of the Russian-speaking Angular Community.
Source: https://habr.com/ru/post/351504/
All Articles