Angular
Dependency Injection
Chau Tran
twitter.com/@nartc1410
github.com/nartc
Agenda
Syntax
export class SomeRepository {}
export class SomeService {
constructor(private someRepository: SomeRepository) {}
}
export class SomeClass {
constructor(private someService: SomeService) {}
}
export class SomeRepository {}
export class SomeService {
@Autowired()
private someRepository: SomeRepository;
}
export class SomeClass {
@Autowired()
private someService: SomeService;
}
@Injectable({ providedIn: 'root' })
export class OneService {}
@Injectable()
export class TwoService {}
@Component({
/* ... */,
standalone: true,
providers: [TwoService]
})
export class SomeComponent {
constructor(
private oneService: OneService,
private twoService: TwoService
) {}
}
Injector
bootstrapApplication(AppComponent);
bootstrapApplication(AppComponent);
bootstrapApplication(AppComponent);
RootInjector
PlatformInjector
bootstrapApplication(AppComponent);
RootInjector
PlatformInjector
providedIn: 'root'
providedIn: 'platform'
import { bootstrapApplication } from '@angular/platform-browser';
bootstrapApplication(AppComponent);
RootInjector
PlatformInjector
providedIn: 'root'
providedIn: 'platform'
import { bootstrapApplication } from '@angular/platform-browser';
bootstrapApplication(AppComponent);
RootInjector
PlatformInjector
providedIn: 'root'
providedIn: 'platform'
import { bootstrapApplication } from '@angular/platform-browser';
bootstrapApplication(AppComponent);
RootInjector
PlatformInjector
providedIn: 'root'
providedIn: 'platform'
NullInjector
ElementInjector
EnvironmentInjector
ElementInjector
(or NodeInjector)
ElementInjector
(or NodeInjector)
@Component({
providers: [/* here */]
})
ElementInjector
(or NodeInjector)
@Component({
providers: [/* here */]
})
@Component({
viewProviders: [
/* here */
]
})
ElementInjector
(or NodeInjector)
@Component({
providers: [/* here */]
})
@Component({
viewProviders: [
/* here */
]
})
@Directive({
providers: [/* here */]
})
ElementInjector
(or NodeInjector)
@Component({
providers: [/* here */]
})
@Component({
viewProviders: [
/* here */
]
})
@Directive({
providers: [/* here */]
})
Component Tree
ElementInjector
EnvironmentInjector
EnvironmentInjector
EnvironmentInjector
ModuleInjector
EnvironmentInjector
EnvironmentInjector
Outside of Component Tree
EnvironmentInjector
Outside of Component Tree
EnvironmentInjector
Outside of Component Tree
RootInjector
PlatformInjector
NullInjector
EnvironmentInjector
@Injectable({ providedIn: '...' })
@Injectable({ providedIn: '...' })
EnvironmentInjector
@Injectable({ providedIn: '...' })
@Injectable({ providedIn: '...' })
bootstrapApplication(AppComponent, {
providers: [/* ... */]
})
EnvironmentInjector
@Injectable({ providedIn: '...' })
@Injectable({ providedIn: '...' })
bootstrapApplication(AppComponent, {
providers: [/* ... */]
})
const routes: Route[] = [
{
/* ... */
providers: [/* ... */],
/* ... */
}
]
EnvironmentInjector
@Injectable({ providedIn: '...' })
@Injectable({ providedIn: '...' })
bootstrapApplication(AppComponent, {
providers: [/* ... */]
})
const routes: Route[] = [
{
/* ... */
providers: [/* ... */],
/* ... */
}
]
@NgModule({
providers: [/* ... */]
})
Injectable
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'any' })
export class AnyService {}
@Component({})
export class AChildComponent {
constructor(private anyService: AnyService) {}
}
@Component({
imports: [AChildComponent]
})
export class AComponent {
constructor(private anyService: AnyService) {}
}
@Component({})
export class BComponent {
constructor(private anyService: AnyService) {}
}
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'any' })
export class AnyService {}
@Component({})
export class AChildComponent {
constructor(private anyService: AnyService) {}
}
@Component({
imports: [AChildComponent]
})
export class AComponent {
constructor(private anyService: AnyService) {}
}
@Component({})
export class BComponent {
constructor(private anyService: AnyService) {}
}
export const routes: Route[] = [
{
path: 'a',
loadComponent: () => import('./a.component').then(mod => mod.AComponent),
},
{
path: 'b',
loadComponent: () => import('./b.component').then(mod => mod.BComponent),
}
]
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Component({
providers: []
})
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Component({
providers: []
})
@Directive({
providers: []
})
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Component({
providers: []
})
@Directive({
providers: []
})
@Component({
viewProviders: []
})
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
@Injectable({ providedIn: 'root' })
@Injectable({ providedIn: 'platform' })
@Injectable({ providedIn: 'any' })
@Injectable()
Inject, InjectionToken
InjectionToken
Inject, InjectionToken
export const API_URL = new InjectionToken<string>('API Base URL');
Inject, InjectionToken
export const API_URL = new InjectionToken<string>('API Base URL');
@Inject(API_WINDOW) private apiUrl: string
Inject, InjectionToken
export const API_URL = new InjectionToken<string>('API Base URL');
@Inject(API_WINDOW) private apiUrl: string
providers: [{ provide: API_URL, useValue: environment.apiUrl }]
Inject, InjectionToken
export const WINDOW = new InjectionToken<Window>('Window');
@Inject(API_WINDOW) private apiUrl: string
providers: [{ provide: API_URL, useValue: environment.apiUrl }]
Inject, InjectionToken
export const WINDOW = new InjectionToken<Window>('Window', {
factory: () => {
}
});
@Inject(API_WINDOW) private apiUrl: string
providers: [{ provide: API_URL, useValue: environment.apiUrl }]
Inject, InjectionToken
export const WINDOW = new InjectionToken<Window>('WIndow', {
factory: () => {
const document = inject(DOCUMENT);
}
});
@Inject(API_WINDOW) private apiUrl: string
providers: [{ provide: API_URL, useValue: environment.apiUrl }]
Inject, InjectionToken
export const WINDOW = new InjectionToken<Window>('Window', {
factory: () => {
const document = inject(DOCUMENT);
return document?.defaultView || null;
}
});
@Inject(API_WINDOW) private apiUrl: string
providers: [{ provide: API_URL, useValue: environment.apiUrl }]
Inject, InjectionToken
export const WINDOW = new InjectionToken<Window>('Window', {
providedIn: '...', // default is 'root'
factory: () => {
const document = inject(DOCUMENT);
return document?.defaultView || null;
}
});
@Inject(API_WINDOW) private apiUrl: string
providers: [{ provide: API_URL, useValue: environment.apiUrl }]
Provider
Provider
Provider
@Injectable({ providedIn: '...' })
Provider
@Injectable()
Provider
@Injectable()
@Component({ providers: [] })
@Component({ viewProviders: [] })
@Directive({ providers: [] })
const route = { providers: [] }
Provider
@Injectable()
interface Provider {
provide: InjectionToken | string;
useClass?: Type;
useFactory: (...args: any[]) => any;
useExisting?: Type;
useValue?: any;
}
Provider
@Injectable()
@Component({
providers: [SomeStore]
})
export class SomeComponent {}
Provider
@Injectable()
@Component({
providers: [
// SomeStore
{ provide: SomeStore, useClass: SomeStore }
]
})
export class SomeComponent {}
Provider
@Injectable()
@Component({
providers: [
// SomeStore
{ provide: SomeStore, useExisting: SomeStore }
]
})
export class SomeComponent {}
@Component({
providers: [SomeStore],
imports: [SomeComponent]
})
export class SomeParentComponent {}
Provider
@Injectable()
{
provide: API_URL,
useValue: environment.apiUrl
}
Provider
@Injectable()
{
provide: API_URL,
useFactory: () => {
return environment.apiUrl
},
}
Provider
@Injectable()
{
provide: API_URL,
useFactory: (configurationService: ConfigurationService) => {
return configurationService.apiUrl;
},
deps: [ConfigurationService]
}
Resolution Modifier
Resolution Modifier
Resolution Modifier
@Optional()
@SkipSelf()
@Self()
@Host()
inject()
Q/A
Angular Dependency Injection
By Chau Tran
Angular Dependency Injection
- 448