Introduction to Angular Modules - Root Module
- Transfer
- Tutorial
Note perev .: to understand this article, you must have basic knowledge of Angular: what components are, how to create a simple SPA application, etc. If you are not familiar with this topic, then I recommend that you first familiarize yourself with the example of creating a SPA application from. documentation.
Introduction
@NgModule
- a decorator added in Angular 2. From the official documentation it follows that @NgModule
defines the class as an Angular module. Angular modules help break down an application into parts (modules) that interact with each other and ultimately represent a complete application. In other words, a module is a package or encapsulation of a part of the application’s functionality. Modules can be designed for reuse, i.e. independent of the specific application implementation.
Please note that if you want to implement lazy load in your application, you must use the Angular Modules concept when designing the application.
Root Module
The root module in an Angular application is used as an entry point. A module is a class that is decorated with @NgModule
. Take a look at the standard code of the module (for example, when creating a new project through ng new project-name
this one is generated AppModule
:
// app.module.ts
@NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule { }
The decorator @NgModule
uses a JavaScript object as an argument .
In the property, declarations
we declare the components that our module contains. In this case, it is a component AppComponent
. There may be several components; they are declared with a comma (as in regular JavaScript array).
declarations: [AppComponent]
Suppose our component has a selector my-app
. When in the HTML template we write the <my-app></my-app>
application loads the component.
How is component loading in the DOM?
AppModule
tells the browser what to embed in the DOM component AppComponent
.
How does it AppModule
add a component to the DOM?
AppModule
imports Angular service modules, for example BrowserModule
, responsible for the operation of 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 directives NgIf
and NgFor
which we can use in component templates.
AppModule
acts as a binder between the data, its presentation and the browser.
Application build
Using the Angular application begins with a file main.ts
, read the manual in more detail .
// 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) , however this is an extensive topic and will be discussed in another article.
Declaration (announcement)
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 property of the declarations
object, which is an argument for the decorator @NgModule
:
// app.module.ts
@NgModule({
imports: [BrowserModule],
declarations: [
AppComponent,
VehicleListComponent,
VehicleSelectionDirective,
VehicleSortingPipe
],
bootstrap: [AppComponent],
})
export class AppModule { }
After the components are declared, we can use them inside other components through their selector, which is indicated in the component description.
Import and nested modules
We import BrowserModule
into AppModule
, which in turn imports CommonModule
, which contains the directives NgIf
and NgFor
available in Angular out of the box. CommonModule
By importing, 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, for example, ngModel
and http
? The solution is simple - we just need to import these modules into AppModule
:
// app.module.ts
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule
],
declarations: [
AppComponent,
VehicleListComponent,
VehicleSelectionDirective,
VehicleSortingPipe
],
bootstrap: [AppComponent],
})
export class AppModule { }
After we imported the module FormsModule
, we can use ngModel
our components in the templates. And HttpModule
it allows us to send or receive data via the HTTP protocol.
Providers
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, 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, which is needed everywhere in our application - an authorization service (Logger Service). Also, our application should show a list of active users, so we need VehicleService
to retrieve a list of active users by accessing the API using http
which we can use thanks to the module HttpModule
. We imported it into our application before.
// 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 introduced 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 { }
Let's describe how it works. We added the creation of the provider object to the constructor of our component, it looks something 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{
constructor (private service: Service){} //Создание объекта сервиса
// Основной код компонента
}
When you create an instance of a component (for example, when we open the page where the component is used), the service object described in the property is simultaneously created providers
(see the listing of app.module.ts above) and Angular starts looking for the class of this service in the parent components. Because we did not declare the provider in the components, eventually Angular will find this service in the root module 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 a service instance has already been created somewhere, then the component will use it; if not, it will create a service object.
Conclusion
Providers, in my opinion, are one of the most interesting and complex concepts of the Angular modular system. The basic rule for 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 upon request.
- Telegram of the Russian-speaking Angular community.