Angular Providers & Angular Decorators - Angular Dependency Injection
In this post you will learn such decorators inside Angular like Optional
, Self
, SkipSelf
and Host
.
Here I already prepared a small project with parent
, child
and app
components.
<parent></parent>
Inside our app.component.html
we just render our parent
.
<div>parent</div>
<child></child>
Inside a parent.component.html
we are rendering child
.
The last thing that we have is a service that we will try to inject.
// users.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
@Injectable()
export class UsersService {
usersKey = 'users';
constructor(private http: HttpClient) {}
getUsers() {
return this.http.get('http://localhost:3004/users');
}
}
Optional decorator
Let's say that our child component really needs a UsersService
. Typically we will provide it like this.
export class ChildComponent implements OnInit {
constructor(private usersService: UsersService) {}
ngOnInit(): void {
console.log('key', this.usersService.usersKey);
}
}
We should not also forget to register it in our app.module.ts
.
@NgModule({
...
providers: [UsersService],
})
export class AppModule {}
But actually we could do it differently. We can remove the registration of this service in the module and just say that it is optional. Then our component will work even if our service is not provided.
export class ChildComponent implements OnInit {
constructor(@Optional() private usersService: UsersService) {}
ngOnInit(): void {
console.log('key', this.usersService?.usersKey || 'not set');
}
}
Here I've added Optional
decorator so in the case if we didn't provide it we won't get an error but null
. This is why I've adjusted ngOnInit
to handle null
correctly and fallback to a default string.
We use Optional decorator when our code can work without a service.
Self decorator
Now let's talk about Self
. Let's add it instead of Optional
.
export class ChildComponent implements OnInit {
constructor(@Self() private usersService: UsersService) {}
}
Now even if we register a service in app.module
we will get an error that usersService
is not provided. It happens because Self
decorator says that we need to register provider inside a component itself.
@Component({
selector: 'child',
templateUrl: './child.component.html',
providers: [UsersService]
})
This is the only way when our Self
decorator will be satisfied.
We use Self decorator when we want to make sure that we registered the dependency in the component itself.
SkipSelf decorator
SkipSelf
works exactly in opposite way. It doesn't not allow us to register a service in our component. Only higher like in parent component or in app module.
export class ChildComponent implements OnInit {
constructor(@SkipSelf() private usersService: UsersService) {}
}
Now our code will break as we registered our service inside component. In order to fix that we can move UsersService
registration to app.module
for example.
We use SkipSelf decorator when we want to make sure that we did NOT registered the dependency in the component itself.
Host decorator
The most interesting decorator is Host
.
@Component({
selector: 'child',
templateUrl: './child.component.html',
providers: [UsersService]
})
export class ChildComponent implements OnInit {
constructor(@Host() private usersService: UsersService) {}
}
Here we used Host
decorator and provided a service in the component again. It allows up to register UsersService
only in components which a visible inside our markup. In our case it is parent and child component.
But here is a catch. If we try to register it in our parent component as a provider it will break. We need to do it differently.
@Component({
selector: 'parent',
templateUrl: './parent.component.html',
viewProviders: [UsersService],
})
export class ParentComponent {}
Instead of providers
we used here viewProviders
. When we have a host decorator it parent providers will be accessible only through viewProviders
but not providers
.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!
📚 Source code of what we've done