Introduction to Angular Modules - Root Module

Original author: John Papa
  • 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 @NgModuledefines 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-namethis one is generated AppModule:


// app.module.ts
@NgModule({
  imports: [BrowserModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
})
export class AppModule { }  

The decorator @NgModuleuses a JavaScript object as an argument .


In the property, declarationswe 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?


AppModuletells the browser what to embed in the DOM component AppComponent.


How does it AppModuleadd a component to the DOM?


AppModuleimports 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. BrowserModulealso includes directives NgIfand NgForwhich we can use in component templates.


image


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 declarationsobject, 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 BrowserModuleinto AppModule, which in turn imports CommonModule, which contains the directives NgIfand NgForavailable in Angular out of the box. CommonModuleBy 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, ngModeland 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 ngModelour components in the templates. And HttpModuleit 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 VehicleServiceto retrieve a list of active users by accessing the API using httpwhich 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, AppModulethey 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.


Also popular now: