Angular2 - How module is different from component? - javascript

In the below code from ../src/app/app.module.ts,
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
Component consists:
view(../src/app/app.component.html)
logic(../src/app/app.component.ts)
style(../src/app/app.component.css)
Angular application is a tree of components. Good components have high cohesion, i.e. each component contains only elements with related functionality. They are also well encapsulated and loosely coupled.
How modules are different from components?

A component is just a class with the #Component() annotation. Note that .html and .css files might be referenced by the component, certainly not mandatory. The component template might very well be 'inlined' directly in the component configuration, or there simply might not be any html template at all for a given component.
A module is a structural element of an Angular application (and maybe other classes and interfaces). It is also "just a class" with the #NgModule() annotation.
It acts as a logical 'container' for your components, directives, services, pipes, etc... to help you structure your overall source code better.
You can have a look at this existing question : What's the difference between an Angular component and module

A module is something that has components. It wraps them up so you can import and manage them.
Notice when you make a component you can put anything that's decorated as #Injectable in your constructor:
#Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
constructor(private myService: MyService) { }
ngOnInit() {
}
}
And magically you will have a myService to use. This is dependency injection, which is built into Angular - but it's managed on a Module level. In your module you import what other modules you want to be able to use:
imports: [
BrowserModule,
FormsModule
],
define what your module includes:
declarations: [
AppComponent,
HeroesComponent,
MyService
],
export any components (so other modules can import them)
exports: [
HeroesComponent
],
They help organize an application into blocks of functionality. Components are things that tell angular how to render something. Modules compose Components, Pipes, Services etc into 'blocks' that can be compiled by angular or imported and used by others.
Edit to address comment
Taking your specific question about HttpClient. The HttpClient is the service you are using to perform the actions. The HttpClientModule is the module you import into your module, so you can use the service it contains.
You import the module:
#NgModule({
imports: [
BrowserModule,
// Include it under 'imports' in your application module
// after BrowserModule.
HttpClientModule,
],
})
And use the service:
#Component(...)
export class MyComponent implements OnInit {
// Inject HttpClient into your component or service.
constructor(private http: HttpClient) {}
...
}
The HttpClientModule contains within it all you need for the HttpClient to work, and packages it up so you can use it in your own projects.
This particular module only wraps up that one service, but the module could contain a bunch of related services, components, pipes or directives. For example, the RouterModule allows you to use the RouterOutlet and RouterLink directives.

Module in angular is set of Components, Services, Filters, or some another smaller modules too, or we can say where you import all these in order to use later in the app for future use. in a single app there can be one or more than one module may exist.
Whereas, A component controls a patch of screen called a view.
You define a component's application logic—what it does to support the view—inside a class. The class interacts with the view through an API of properties and methods.
Refer this guide for more details:
https://angular.io/guide/architecture

Related

Why to import { HttpClientModule } in app.module.ts

I have been working on creating a service to make http requests and hence I'm using HttpClientModule given by Angular. I have data.serivce.ts file where the service is declared and I'm importing the HttpClient as shown below.
import { Injectable } from '#angular/core';
import { HttpClient} from '#angular/common/http'
#Injectable()
export class DataService {
constructor(private http:HttpClient) {
}
validateLogin(){
return this.http.get('https://someurl')
}
}
Since I'm injecting the dependency of DataService in the providers array of the app.module.ts, I don't understand why I need to import the HttpClientModule again in the app.module.ts
You should look into how angular modules work. Your app.module.ts contains AppModule which is a root module. Every application has at least one module i.e. root module. If you import any module inside your AppModule then its (imported module) components will be accessible to every component of your application.
Thats why to make HttpClient available "everywhere" in the app:
import the HttpClientModule inside AppModule.
Now you can use Services, Components etc defined inside HttpClientModule in your own services or components.
For the variable type information you use on this line
constructor(private http:HttpClient)
Without that import, there would be an error since that type would be unknown.
In the Angular docs it says that the HttpClientModule, "Configures the dependency injector for HttpClient with supporting services for XSRF." So it looks like that's why it would be a prerequisite for using the HttpClient.
https://angular.io/api/common/http/HttpClientModule#description
https://angular.io/tutorial/toh-pt6

Using Angular to declare a new service instance per module?

I'm using angular. I already know that when an appmodule is importing modules which declares providers, the root injector gets them all and the service is visible to the app - globally. (I'm not talking about lazy loaded modules)
But is it possible that each module will have its own instance of the service?
I thought of maybe something like this :
#NgModule({
providers: [AService]
})
class A {
forRoot() {
return {
ngModule: A,
providers: [AService]
}
}
forChild() {
return {
ngModule: A,
providers: [AService]
}
}
}
But I don't know if it's the right way of doing it
Question
How can I accomplish service per module ?
STACKBLITZ : from my testing , they are using the same service instance
When we provide a service in a feature module that is eagerly loaded
by our app's root module, it is available for everyone to inject. - John Papa
So looks like there is no way to inject at feature-module level, as there are no module level injectors other than the one at root module.
But angular has nodes at each component level for the injector, so such a scenario will have to use coponent level-injectors I guess.
You can also have a parent component inject the service for different children sharing the same instance.
One way is to provide the services at component level. Not sure if that will work for you.
Also, check the multiple edit scenario in the docs
https://angular-iayenb.stackblitz.io
import { Component, OnInit } from '#angular/core';
import {CounterService} from "../../counter.service"
#Component({
selector: 'c2',
templateUrl: './c2.component.html',
styleUrls: ['./c2.component.css'],
providers:[CounterService]
})
export class C2Component implements OnInit {
constructor(private s:CounterService) { }
ngOnInit() {
}
}
Question
How can I accomplish service per module ?
Not with the default Injector. Default Injector keeps nodes at root level and component level, not at feature-module level. You will have to have a custom Injector if there is a real scenario.
Edit: the previous answer from me is not completely correct. The correct way to make this work is to use lazy loaded modules, provide the services there. The given service should not be provided with a static forRoot() method somewhere because then the lazy loaded module will access the root injector.
There is no actual reference to do so because that is not how angular is designed but if you want it that way you have to the opposite of
https://angular.io/guide/singleton-services#providing-a-singleton-service
and
https://angular.io/guide/singleton-services#forroot
Old not completely correct:
You simple have to declare the service you want to be single instance for each and every module within the providers meta data of each and every module. Then Angular will not reuse any instance of the service.
Giving scenario: You have two modules, ModuleA and ModuleB, both need the service but different instance, then you will declare them in the providers section of ModuleA and ModuleB.
Reference:
https://angular.io/guide/singleton-services

Angular4/5 dependency injection docs not working

https://angular.io/guide/architecture#services
I'm following the docs on angular.io to inject dependencies like services, etc. I did everything they said and when I try to run it, the console keeps telling me:
Uncaught ReferenceError: LedgerService is not defined
I am doing nothing crazy except creating a simple component with a service where both constructors have console.log commands (constructors in both the component and service). I've done everything Angular says to do in their 2 paragraphs that details this feature of Angular.
The component itself is being injected into the main app module (with the service being injected into the component) and both the component and service were created with the Angular CLI. So there isn't much I've even done at all minus trying to inject the service. So I'm not sure where it is going wrong but it is definitely not working and just shows a blank page (when it previously had basic content by default).
I created both units, tried to specify providers in both the app.module and the component.ts file and neither works and yields the same error--when Angular claims either could work. I've also specified it as a private service within the constructor of the component.ts file.
Everything I've seen relating to this is always for Angular 1 or 2. Neither of which are even remotely similar to Angular 4/5.
If you really want to see this code, fine but it's literally just framework and nothing else:
bookkeeper.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-bookkeeper',
templateUrl: './bookkeeper.component.html',
styleUrls: ['./bookkeeper.component.css'],
providers: [LedgerServiceService]
})
export class BookkeeperComponent implements OnInit {
constructor(private service: LedgerServiceService) { }
ngOnInit() {
console.log("Ledger component works!");
}
}
app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { InterfaceComponent } from './interface/interface.component';
import { BookkeeperComponent } from './bookkeeper/bookkeeper.component';
#NgModule({
declarations: [
AppComponent,
InterfaceComponent,
BookkeeperComponent
],
imports: [
BrowserModule
],
providers: [
LedgerServiceService
],
bootstrap: [AppComponent]
})
export class AppModule { }
ledger-service.service.ts:
import { Injectable } from '#angular/core';
#Injectable()
export class LedgerServiceService {
constructor() {
console.log("wtf");
}
}
LedgerService is actually called LedgerServiceService because I initially created LedgerService manually and then tried to use the AngularCLI to generate a service and named it LedgerService and it created a service called LedgerServiceService. Naming is not what is wrong. I only initially called it simply LedgerService because I figured it would be confusing.
Your examples are missing the import.
Anywhere we use a custom type, we also need to import that type.
For that reason, in both the module and component you will need to add:
import { LedgerServiceService } from './your-path-here'
You can see this in the examples they give on https://angular.io/guide/dependency-injection

Angular 2: Rendering angular html components from webservice

I am looking for how to add html which is a return of the web service, in angular. The problem is that the angular directives do not rendered. here is my source code
//tohtml.directive.ts
import { Directive, ElementRef, OnInit } from '#angular/core';
#Directive({
selector: '[appToHtml]'
})
export class ToHtmlDirective {
constructor( private el: ElementRef) {}
tohtml() {
//it is assumed that this is the return of the webservice
this.el.nativeElement.innerHTML = '<a
[routerLink]="/link/to/page">helpful!
</a>';
}
}
Code for component.html
<div id="wrapper">
<h1 appToHtml>
Hello World!
</h1>
</div>
the code works, but the rendering of the [routerLink] does not work, pleaseee hellppp !!!
By setting innerHTML prop in your directive you only set DOM and attributes. But this content need to be compile by angular to allow angular-like behavior (binding directives, instanciating components etc..) .
Angular dont have compiler ready to use like angularJS ( which has $compile ). You need to use 3rd party libraries like
https://www.npmjs.com/package/p3x-angular-compile
or
https://www.npmjs.com/package/ngx-dynamic-template
Those lib comes with handy examples. You should easily understand how to use them.
Be aware that you cant use AOT with such a rendering system.
Edition for ngx-dynamic-template usage :
if your dynamic templates need some directive of component, you have to configure ngx-dynamic-template to import the corresponding modules.
You can create a dynamic module like that in your case
#NgModule({
imports: [
RouterModule
],
exports: [
RouterModule
]
})
export class DynamicModule {}
and then when importing ngx in your appModule or SharedModule
#NgModule({
imports: [
...
NgxDynamicTemplateModule.forRoot({extraModules: [DynamicModule]})
...
],
Then you will be able to use routerLink without problem (i just tested)
in cmpt :
htmlTemplate = `<a [routerLink]="['dress-options']">link to user component</a>`;
in template :
<div dynamic-template [template]="htmlTemplate"></div>
With the latest angular version for me only this module works fine: https://www.npmjs.com/package/ngx-dynamic-template
v2.1.24 for angular4, v.2.3.0 is for angular5

What is the exact meaning of export keyword in Angular 2\TypeScript?

I am pretty new in Angular 2. I am studying how to create modules into an Angular app and I have the following doubt related a tutorial that I am following.
My doubt is related to the routing.
So in my example there is defined this AuthModule module:
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { SigninComponent } from './signin/signin.component';
import { SignupComponent } from './signup/signup.component';
import { AuthRoutingModule } from './auth-routing.module';
#NgModule({
// Components and directives used by the module:
declarations: [
SigninComponent,
SignupComponent
],
// Import modules used by this features module:
imports: [
FormsModule,
AuthRoutingModule
]
})
export class AuthModule {}
and I have the related rotues configuration class defined:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { ShoppingListComponent } from './shopping-list/shopping-list.component';
const appRoutes: Routes = [
{ path: '', redirectTo: '/recipes', pathMatch: 'full' },
{ path: 'shopping-list', component: ShoppingListComponent }
];
#NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
So I think that the export keyword means that the content related to this class can be exported and used somewhere else (in this case I think into the imports array of the AuthModule class).
Is it? Or am I missing something? What it the exact meaning of the export statment?
I am not understanding if it is something related to Angular or more generally to TypeScript (because here I found https://www.typescriptlang.org/docs/handbook/modules.html). So it seems to me that this module concept is not directly bounded to Angular 2 framework but is a TypeScript concept to subdivide our code in a smart way (then Angular 2 can use this kind of feature of the language).
Is it or am I missing something?
Angular imports/exports and TypeScript imports/exports are two different concepts.
TypeScript imports/exports work at language level to make it clear what
a used identifier references exactly. This is entirely unrelated to Angular.
So, if you use FormsModule there can't be any ambiguity, what FormsModule is meant. If there is more than one FormsModule in your code or any of your dependencies, then you need to make it clear with imports which one is meant. You can't import 2 FormsModule from different locations without disambiguation (for example using as foo in the import and then reference it using foo.FormsModule).
This way you can use code from arbitrary 3rd-party libraries and avoid name collisions.
Angular imports/exports are used to make the content of one module available to be used in another module.
Your:
imports: [
FormsModule,
AuthRoutingModule
]
Allows you to use the directives from FormsModule and AuthRoutingModule in AuthModule and registers the services provided by these modules in the AppModule scope or the closed lazy-loaded root scope.
If you reference any of Angulars directives or services in TypeScript code, you also need to add TypeScript imports. Above FormsModule and AuthRoutingModule need to be imported with TypeScript imports, to make the Angular imports: [...] work.
For example like
<form #f="ngForm">
<input type="text">
</form>
works only if FormsModule is listed in imports: [ ... ] of your current module.
There is no TypeScript import required, because there is no TypeScript code.
Yes you are right by using export keyword before your typescript class you can use that class somewhere else .. in your project

Categories