I am completely new to Angular2 and it has been very difficult to understand what is going on with the @NgModule
imports and exports in Angular2.
Take the following code for example-:
@NgModule({ imports: [ RouterModule.forChild(heroesRoutes) ], exports: [ RouterModule ] })
In the imports section what am I importing ? The router module , or the forChild() function, or the module returned by the function forChild() ? Which one is it ?
Also when I export the RouterModule
again, the documentation says the following-:
Our last step is to re-export the RouterModule. By re-exporting the RouterModule, our feature module will be provided with the Router Directives when using our Routing Module.
So does that mean that whatever module imports the above NgModule, will have access to all the code in the RouterModule ?
Is it sort of like if I write a custom header file in C that includes math.h, if I now use that header file I no longer need to include math.h in my programme separately. Is my analogy correct ?
Can someone explain the core concepts here, so that I don't get stumped every time I see new code.
An import is what you put in the imports property of the @NgModule decorator. It enables an Angular module to use functionality that was defined in another Angular module. An export what you put is the exports property of the @NgModule decorator.
exportslink The set of components, directives, and pipes declared in this NgModule that can be used in the template of any component that is part of an NgModule that imports this NgModule. Exported declarations are the module's public API. A declarable belongs to one and only one NgModule.
In Angular, a module is a mechanism to group components, directives, pipes and services that are related, in such a way that can be combined with other modules to create an application. An Angular application can be thought of as a puzzle where each piece (or each module) is needed to be able to see the full picture.
A Module in Angular2 is very similar to the Angular1 modules , which basically is a package containing all the bits and pieces that makes sense to be shipped together.
For example , if you have a LoginComponent which for some reasons is connected to a Service , which is LoginService, which does some http request to get some user information , you might create a LoginModule which ships LoginComponent and LoginService all together as LoginModule.
LoginService could also use some interfaces , for example a UserInterface , which again , would makes sense to be shipped to LoginModule to the consumer.
So if I'm your client and I'm going to use your general Login functionality , would makes it much easier for me to just import your LoginModule and all your goodies available to my AppComponent !
So , your LoginModule class ( which is nothing but a simple javascript file and a function ) should export LoginModule to be used by me :).
LoginModule would look like this:
@NgModule({ declaration:[LoginComponent , LogoutComponent], exports: [ LoginComponent , LogoutComponent ], providers:[LoginService] }) export class LoginModule{ }
So in my AppModule , I would import your LoginModule.
@NgModule({ imports: [ LoginModule, RouterModule.forChild(heroesRoutes) // another imported module that I need beside the Login ] })
BUT :
If I know your code and I don't want any of your extra functions and components and classes and things and I just need to use your LoginComponent , I might prefer to only declare that I'm using LoginComponent and I don't want to import your massive LoginModule !
@NgModule({ declaration:[LoginComponent], imports: [ RouterModule.forChild(heroesRoutes) ] })
This would only and only work if LoginComponent does not have any direct dependency on LoginService , other wise Angular would complain and say :
**No Provider for LoginService**
Which in that case , if you're a tough person and you're still not convinced to use LoginModule , you can help Angular and provide the LoginService like :
@NgModule({ declaration:[LoginComponent],// declaring it providers:[LoginService],// providing it imports: [ RouterModule.forChild(heroesRoutes) ] });
So , this might continue and you might find it easier to just import the whole LoginModule and let the Module itself do all of the job .!
That's it with LoginModule.
Now , to answer your question regarding forChild.
The LoginModule might want to do some extra things when giving you it's classes which is not always needed , in that case you might have improved the LoginModule and added some sugar to it.
@NgModule({ declaration:[LoginComponent , LogoutComponent], exports: [LoginComponent , LogoutComponent], providers:[LoginService] }) export class LoginModule{ public static logAndLoadModule(message){ console.log('I first log and then give you my module'); return { ngModule: LoginModule } } public static alertAndLoadModule(message){ alert('I first alert and then give you my module'); return { ngModule: LoginModule } } }
Which , in this case , looks like the module can log something when it starts giving me it's package . So I might use it like this:
@NgModule({ imports: [ LoginModule.logAndLoadModule(), RouterModule.forChild(heroesRoutes) ] })
Isn't logAndLoadModule this similar to forChild function of RouterModule ?
Yes it is , it still gives you LoginModule but it does some extra thing as well.
So you can still import LoginModule , but you can use it's alert and log as well.
UPDATE:
export class LoginModule , means , the current file ( probably login.module.ts or whatever ) is exporting a class called LoginModule which can be imported from other files and it has nothing to do with Angular , this is only typescript which will compile to javascript.
Where as
@NgModule({ exports: [ LoginModulesBrother ] }) export class LoginModule{ }
Above is Angular2 specific language and means LoginModule is also Exporting LoginModulesBrother , so who ever is importing LoginModule , has also have access to to LoginModulesBrother.
So , LoginModulesBrother , is another module which is probably defined somewhere else like :
@NgModule({ // some other magic here }) export class LoginModulesBrother{ }
So generally , import and export a class , which could be what ever ( a Module a component a pipe a simple function or anything ) is only typescript , but that exports array and imports array is only Angular specific language and means nothing to typescript .
If you use the <router-outlet>
component or the routerLink
or routerLinkActive
directives, you need to add the RouterModule
to imports: []
of every module where you want to use any of these.
This is the same for any directive, component or pipe. Angular only instantiates them in a module if they are made known by an import.
If you add a module to imports: []
all directives, components and pipes listed in exports become available to the importing module.
A module also can re-export other modules, which makes all exported directives, components and pipes of these modules available to the importing module.
See also
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With