How to use angular material api services? - javascript

I am a beginner to the angular world, I was using the angular material's "Sort header" component, and on the API tab (https://material.angular.io/components/sort/api) there is something called services, and I want to use them, But I don't get it how do to use it.
For example:
On the API tab of "Sort header" or (https://material.angular.io/components/sort/api)
I want to use the service "MatSortHeaderIntl",
it has some properties such as - sortDescriptionLabel
So please tell me how to use "sortDescriptionLabel" property of "MatSortHeaderIntl" service.
Thanks.

You need to import, and provide it to your module
import {MatSortHeaderIntl} from '#angular/material';
#NgModule({
imports: [
...
],
entryComponents: [..],
declarations: [...],
bootstrap: [...],
providers: [MatSortHeaderIntl]
})
export class AppModule {}
Then in whatever component you want to use it, instantiate it
constructor( private matSortService: MatSortHeaderIntl) {}
and you can call it by scope
this.matSortService.<method>
I setup an example of Integrated MatSortHeaderIntl Service

Related

NestJS - how to provide services of dynamic modules

I'm struggling to figure out on how to provide services from DynamicModule to regular Modules. Pseudocode below:
app.module.ts
#Global()
#Module({
imports: [
DynamicModule.forRoot(config),
RegularModule,
],
providers: [],
exports: [],
})
export class AppModule {}
dynamic.module.ts
#Module({})
export class DynamicModule implements OnModuleInit, OnModuleDestroy {
constructor(private dynamicService: dynamicService) {}
static forRoot(config: Config): DynamicModule {
return {
module: DynamicModule,
imports: [],
providers: [
{
provide: CONFIG_TOKEN,
useValue: config,
},
DynamicService,
],
exports: [
DynamicService,
],
};
}
}
dynamic.service.ts
#Injectable()
export class DynamicService {
constructor(
#Inject(CONFIG_TOKEN) private readonly config: Config,
) {}
}
regular.module.ts
#Module({
imports: [],
providers: [RegularService, DynamicService],
exports: [RegularService],
})
export class RegularModule {}
regular.service.ts
#Injectable()
export class RegularService {
constructor(
private readonly dynamicService: DynamicService
) {}
}
Providing DynamicService to RegularModule requires to provide CONFIG_TOKEN in RegularModule as well, which seems odd and not practical in case more modules would depend on DynamicService and doesn't seem to be the correct way.
What concepts am I missing and what is correct approach to use services of a DynamicModule?
Would something as forFeature in DynamicModule method would be the right direction?
dynamic modules are modules that need some sort of context defined input, classic example is a database module that would need at least the host url and credentials, which would vary by app.
This means that when the forRoot(input) returns, you have a module just like any regular (non dynamic) module. As such, you can make use of the config value inside the dynamic module's service, export the service on the dynamic module, and then inject that service on other modules that import your dynamic module.
There is no need to also inject the config value on the service that injected the dynamicService.
If you need to have direct access to the config value inside of regularService, and that value is being shared across multiple services and modules, then you should take a look at the ConfigModule and treat that config value as env. If by some very specific reason it cant or should not be in env, then still you should create a separate module for providing this config values.

Add providers post-declaration of AppModule

Angular 2+ registers providers in the following way:
// #NgModule decorator with its metadata
#NgModule({
declarations: [...],
imports: [...],
providers: [<PROVIDERS GO HERE>],
bootstrap: [...]
})
export class AppModule { }
I want to register application-scoped providers separately from this declaration site.
Specifically, I am using NSwag to generate service clients for my entire Web API and I want to dynamically add them all as providers. However, I'm not sure how to do that since #NgModule is an attribute applied to this AppModule class.
Is this possible?
Any DI provider needs to be included in the module at compile time.
Since Angular dependency injection works with Typescript type symbols / tokens, there's no Javascript functionality to accomplish the same task after it's compiled.
What you can do is dynamically add the provider at compile time, like so:
import { Load, SomeToken } from '../someplace';
#NgModule({
declarations: [...],
imports: [...],
providers: [
{
provide: SomeToken,
useValue: Load(someVariable)
],
bootstrap: [...]
})
export class AppModule { }
and then implement the Load function and token elsewhere:
export const SomeToken = new OpaqueToken<any>('SomeToken');
export const Load = (someVariable) => {
// logic to return an #Injectable here. Variable provided could be something like an environment variable, but it has to be exported and static
}
This approach of course has the limitation of needing to be known at compile time. The other approach is to either globally import all providers that are needed throughout the app regardless of circumstance and then lazy load components that have the appropriate provider injected for that circumstance (Angular will not initialize the provider until a component that utilizes it is initialized), or create a provider that in itself is able to perform the logic regardless of the dynamic criteria. An idea for that is to create another service that utilizes this service and resolves things based off of that dynamic criteria (i.e. you could have a method called GetLoginInfo on the first service and the second service would be able to resolve the correct API call for that method.)
If it's just API information you need (i.e. URLs), then you could possibly achieve the above by grabbing the URL information from a config.json file or API call, and inject those values into the service so the calls and tokens remain the same but use different values. See here for more information on how to accomplish that.

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

Angular2 - How module is different from component?

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

Force service instantiation in Angular 2 sub-module (an alternative to AngularJS run block)

I have a service in sub-module that wraps some third-party module, instantiates and initializes its service to prepare for use within app.
#Injectable()
class SubmoduleInitializerService {
constructor (thirdPartyService: ThirdPartyService) {
thirdPartyService.initialize(...);
...
}
}
#NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService
]
})
class AppSubmodule {}
ThirdPartyService isn't injected in app directly but is used by other ThirdPartyModule units, so as long as SubmoduleInitializerService is injected in the same injector as ThirdPartyService or parent injector, everything is fine:
export class AppComponent {
constructor(
/* DO NOT REMOVE! BAD THINGS HAPPEN! */
submoduleInitializerService: SubmoduleInitializerService
) {}
...
}
It was proven to be a lousy pattern because it is not obvious why SubmoduleInitializerService should stay injected in AppComponent if it's not used neither in class nor in template (was accidentally removed once already).
Basically AppSubmodule module needs an alternative to Angular 1.x angular.module(...).run(...) block.
What are the options here?
APP_INITIALIZER (undocumented) service plays the role of AngularJS config/run blocks reasonably well in Angular 2 (not counting the feature of asynchronous initialization).
For noop intialization block that just eagerly instantiates SubmoduleInitializerService it is:
#NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService,
{
provide: APP_INITIALIZER,
useFactory: () => () => {},
deps: [SubmoduleInitializerService],
multi: true
}
]
})
class AppSubmodule {}
Since APP_INITIALIZER is multi-provider, it allows to have several initialization functions per application that follow the order in which the modules are being loaded.
For synchronous initialization the shorter (and probably more appropriate) alternative is to inject the service into module's constructor:
#NgModule({
imports: [ThirdPartyModule],
exports: [ThirdPartyModule],
providers: [
ThirdPartyService,
SubmoduleInitializerService
]
})
class AppSubmodule {
constructor(sis: SubmoduleInitializerService) {}
}
As explained in this answer, APP_INITIALIZER shares some traits with config block, too, because it is used to configure services prior to component initialization and is susceptible to race conditions (for example, since APP_INITIALIZER is used to configure Router, injecting it into another APP_INITIALIZER will result in circular dependency).

Categories