Can Injectable Services have a providers list? - dart

I was doing some code with a component class and a service class.
#Injectable()
class MyService extends Object {
...
}
#Component(
...
providers: const [MyService]
)
class myCompoment implements onInit {
final MyService _service;
MyComponent(this._service);
...
}
Is there a way to say, give a provider to my injectable service such that it can consume? When looking online, it had shown that Component comes from Injectable, so I was thinking to create a component out of the service, but that doesnt quite make sense as to me a component would also have UI.
Ideally, I wanted to do something like:
#Injectable()
class AnotherClass {}
#Injectable(providers: const [AnotherClass])
class MyService extends Object {
...
}
#Component(
...
providers: const [MyService]
)
class myCompoment implements onInit {
final MyService _service;
MyComponent(this._service);
...
}
but Injectable doesnt allow the providers property it seems.

You can add providers: const [MyService, AnotherClass] to components and MyService can inject AnotherClass by just listing it as constructor parameter
#Injectable()
class AnotherClass {}
#Injectable()
class MyService extends Object {
final AnotherClass _anotherClass;
MyService(this._anotherClass);
}
#Component(
...
providers: const [MyService, AnotherClass]
)
class myCompoment implements onInit {
final MyService _service;
MyComponent(this._service);
...
}

Related

How to inject service inside a guard Nest js

I have created a guard for global use. Whenever I am trying to inject my user service into the guard getting this error while compiling - Nest can't resolve dependencies of the VerifyUserGuard (?). Please make sure that the argument dependency at index [0] is available in the UserModule context.
My user service is a part of user module and inside the user service I have used #InjectRepository(User) private readonly _usersRepository: Repository<User>
Guard -
import { CanActivate, ExecutionContext, Injectable } from '#nestjs/common';
import { UserService } from '#v1/user';
import { VerifyUserDto } from '#v1/user/dto';
#Injectable()
export class VerifyUserGuard implements CanActivate {
//getting error because of this
constructor(private _userService: UserService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest<Request>();
const requestBody = request.body as unknown as VerifyUserDto;
console.log(requestBody);
const user = await this._userService.findOneByEmail(requestBody.email);
return true;
}
}
User module -
import { MailModule } from '#mail';
import { Module } from '#nestjs/common';
import { UserService } from './user.service';
import { User } from './entities/user.entity';
import { TypeOrmModule } from '#nestjs/typeorm';
import { UserController } from './user.controller';
#Module({
imports: [MailModule, TypeOrmModule.forFeature([User])],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
I believe you need
either to inject your module or service (with providing if not module) in AppModule if you connect your guard
or use #Global() decorator for your module with service, e.g.
#Global()
#Module({
imports: [MailModule, TypeOrmModule.forFeature([User])],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
Try this It worked for me. Use #Inject Decorator.
constructor(#Inject(AppService) private _userService: UserService) {}

Can this kind of dependency injection be achieved with NestJS?

I want to inject the result of a Nest service method as dependency in a short way. Example is a logging facility, where a child logger is derived from the main logger with a new prefix.
It should be something like this (long version):
#Injectable()
class MyService {
private logger;
constructor(private loggerService: LoggerService) {
this.logger = loggerService.getChildLogger('prefix');
}
someMethod() {
this.logger.info('Hello');
}
}
But in a short version, something like this - maybe with a decorator:
#Injectable()
class MyService {
constructor(#logger('prefix') logger: LoggerService) {
}
someMethod() {
this.logger.info('Hello');
}
}
You could create providers for your loggers using factories injecting your LoggerService :
The LoggerService:
#Injectable()
export class LoggerService {
getChildLogger(scope: string) {
return new Logger(scope);
}
}
The MyService:
#Injectable()
export class MyService implements OnModuleInit {
constructor(#Inject('MY_SERVICE_LOGGER_TOKEN') public childLogger) {}
onModuleInit() {
this.childLogger.log('Hello World');
}
}
The module:
#Module({
providers: [
LoggerService,
MyService,
{
provide: 'MY_SERVICE_LOGGER_TOKEN',
useFactory: (loggerService) => loggerService.getChildLogger('scope'),
inject: [LoggerService]
},
]
})
export class MyModule {}
There is now a solution provided by Livio Brunner:
https://github.com/BrunnerLivio/nestjs-logger-decorator

What is the difference between #Inject and #Injectable in Angular 2 typescript

I don't understand When to use #Inject and when to use #Injectable ?
import {Component, Inject, provide} from '#angular/core';
import {Hamburger} from '../services/hamburger';
export class App {
bunType: string;
constructor(#Inject(Hamburger) h) {
this.bunType = h.bun.type;
}
}
And..
import {Injectable} from '#angular/core';
import {Bun} from './bun';
#Injectable()
export class Hamburger {
constructor(public bun: Bun) {
}
}
The #Injectable decorator aims to actually set some metadata about which dependencies to inject into the constructor of the associated class. It's a class decorator that doesn't require parameters. Without this decorator no dependency will be injected...
#Injectable()
export class SomeService {
constructor(private http:Http) {
}
}
The #Inject decorator must be used at the level of constructor parameters to specify metadata regarding elements to inject. Without it, the type of parameters is used (obj:SomeType is equivalent to #Inject(SomeType) obj).
#Injectable()
export class SomeService {
constructor(#Inject(Http) private http:Http, #Inject('sometoken') obj) {
}
}
You must read this difference- #Inject and #Injectable
#Inject()
is a manual mechanism for letting Angular know that a parameter must be injected.
When using TypeScript, #Inject is only needed for injecting primitives.
For eg:
export class AppComponent {
encryption = this.chatWidget.chatSocket.encryption;
constructor(#Inject(ChatWidget) private chatWidget) { }
}
#Injectable()
lets Angular know that a class can be used with the dependency
injector.
For eg:
#Injectable()
export class ChatWidget {
constructor(
public authService: AuthService,
public authWidget: AuthWidget,
public chatSocket: ChatSocket) { }
}
In the above example Angular's injector determines what to inject into ChatWidget's constructor by using type information

Service class is not injected in Angular2

I already had everything working yesterday. And today, after I restarted the environment, one of the services that I am trying to inject, is now always null.
Here is my top level component (app.component.ts):
#Component({
selector: 'priz-app',
moduleId: module.id,
templateUrl: './app.component.html',
directives: [ROUTER_DIRECTIVES, SecureRouterOutlet],
providers: [ROUTER_PROVIDERS, AuthenticationService]
})
The template of that component contains:
<secure-outlet signin="Login" unauthorized="AccessDenied"></secure-outlet>
Where the secure-outlet implementation is as follows:
#Directive({
selector: 'secure-outlet'
})
export class SecureRouterOutlet extends RouterOutlet {
#Input()
signin: string;
#Input()
unauthorized:string;
#Input()
nameAttr: string;
constructor(_elementRef: ElementRef, _loader: DynamicComponentLoader,
private parentRouter: Router,
private authService: AuthenticationService,
public injector: Injector) {
super(_elementRef, _loader, parentRouter, null);
}
...
In the constructor, as well as anywhere else in the directive, authService is always null. I tried, defining providers with AuthenticationService inside the directive, in the main component, even in the bootstrap, nothing works.
What am I missing?
Thanks,
Don't add providers: [ROUTER_PROVIDERS] to components, only to bootstrap()
Try providing the same parameters as the original RouterOutlet class and add your own dependencies behind them.
Not sure if this helps though but I think it was mentioned not too long ago that there is a weird issue:
constructor(
_elementRef: ElementRef,
_loader: DynamicComponentLoader,
private parentRouter: Router,
#Attribute('name') nameAttr: string, // <= added
private authService: AuthenticationService,
public injector: Injector) {

How to instantiate/inject class declared in main component to another component

My AppComponent sample:
///other imports here
import { ApplyColor } from './../../shared/directives/applycolor';
import { SomeComponent} from './../../components/somecomponent';
#Component({
selector: 'my-app',
directives: [ApplyColor, ROUTER_DIRECTIVES],
providers: [ROUTER_PROVIDERS],
templateUrl: 'myurl.html'
})
#RouteConfig([
//routes here
{ path: '/main', name: 'Main', component: SomeComponent, useAsDefault: true },
])
export class AppComponent {
}
In order to instantiate ApplyColor in SomeComponent
Import ApplyColor
Add to directives: [ApplyColor]
Instantiate with a new keyword
Which is:
import {Component, AfterViewInit, ViewChild} from 'angular2/core';
import { ApplyColor } from './../../shared/directives/applycolor';
#Component({
selector: 'my-selector',
directives: [ApplyColor],
templateUrl: 'app/components/mycomponenturl.html'
})
export class MyComponent implements AfterViewInit {
constructor() { }
ngAfterViewInit() {
var color = new ApplyColor();
color.apply(2);
}
}
How can I instantiate/inject ApplyColor without there 3 steps above?
Directive instances are managed by Angular2. This means that you only need to specify it into the directives attribute. So if ApplyColor is a directive just add it into the directives attribute.
If ApplyColor isn't a directive, you can explicitly instantiate into the provide to the child component using #Input.
In your case, it's a bit particular since you leverage routing. In this case, you need to rely on a shared service. Such service needs to be defined when bootstrapping the application to be able to share a single instance for all components. You can set your instance of ApplyColor into a field of this service. So both component (AppComponent and SomeComponent) can access it.
Define the service
export class SharedService {
color:ApplyColor;
}
Bootstrapping the service
bootstrap(AppComponent, [ SharedService ]);
Set color from AppComponent
#Component({
(...)
})
export class AppComponent {
constructor(private service:SharedService) {
var color = new ApplyColor();
this.service.color = color;
}
}
Get color from SomeComponent
#Component({
(...)
})
export class AppComponent {
constructor(private service:SharedService) {
this.service.color.apply(2);
}
}
I have just started working angular2 but as I can understand:
import ApplyColor => you can't remove that, it required by the compiler to know which class you are referenced to
directives : [ApplyColor] => that means you will use the selector (the one you have defined in applycolor.ts) in the template (app/components/mycomponenturl.html). it is only to know where the component will be in the view.
new ApplyColor => you are creating the object yourself, it is not injected.
To inject your component,
export class MyComponent implements AfterViewInit {
constructor(private color:ApplyColor) { }
ngAfterViewInit() {
this.color.apply(2);
}
}
I hope it helped you ?

Resources