The Injector Hierarchy
Angular's DI system is hierarchical. Each component and directive has its own injector that inherits from its parent. This creates a tree of injectors that mirrors the component tree.
Injector Tree
RootInjector (providedIn: 'root')
├── AppComponent injector
│ ├── HeaderComponent injector
│ │ └── NavComponent injector
│ └── MainComponent injector
│ └── ChildComponent injector
└── LazyModule injector
└── LazyComponent injector
Component-Level Providers
@Component({
selector: 'app-user-list',
template: `<app-user-card *ngFor="let user of users" [user]="user"></app-user-card>`,
providers: [UserService], // New instance for this component subtree
})
export class UserListComponent {
constructor(private userService: UserService) {}
}
Each UserListComponent gets its own UserService instance. Child components (UserCardComponent) receive the same instance.
Provider Scope Comparison
| Scope | Syntax | Instance |
|---|---|---|
| Root | providedIn: 'root' |
One per app |
| Module | providedIn: SomeModule |
One per module |
| Component | providers: [Service] |
One per component |
| Environment | EnvironmentInjector |
App-wide, outside component tree |
ViewProviders vs Providers
@Component({
selector: 'app-parent',
template: `<ng-content></ng-content>`,
viewProviders: [Service], // Only available to this component's view, not projected content
})
export class ParentComponent {}
providers— available to the component, its view, and projected contentviewProviders— available only to the component's own view (not ng-content)
EnvironmentInjector and runInInjectionContext
EnvironmentInjector provides application-wide providers outside the component tree. It is useful for functional guards, resolvers, and utility functions.
EnvironmentInjector
import { EnvironmentInjector, inject, runInInjectionContext } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class AppService {
constructor(private envInjector: EnvironmentInjector) {}
doSomething(): void {
runInInjectionContext(this.envInjector, () => {
const router = inject(Router);
router.navigate(['/']);
});
}
}
createEnvironmentInjector
import { createEnvironmentInjector, EnvironmentInjector } from '@angular/core';
const parentInjector = inject(EnvironmentInjector);
const customProviders = [
{ provide: API_URL, useValue: 'https://custom-api.com' },
];
const childInjector = createEnvironmentInjector(customProviders, parentInjector);
Practical Use Case: Feature Flags
export const FEATURE_FLAGS = new InjectionToken<FeatureFlags>('FEATURE_FLAGS');
// In app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
{
provide: FEATURE_FLAGS,
useValue: { newDashboard: true, betaFeature: false },
},
],
};
// In a component
@Component({
selector: 'app-dashboard',
template: `
@if (flags().newDashboard) {
<app-new-dashboard />
} @else {
<app-old-dashboard />
}
`,
})
export class DashboardComponent {
flags = inject(FEATURE_FLAGS);
}
When to Use Each Scope
| Scenario | Scope |
|---|---|
| HTTP client, auth service | Root |
| Feature module services | Module |
| Component-specific state | Component |
| Configuration, feature flags | Environment |
Quiz
1. What does a component-level provider create?
2. What is the difference between providers and viewProviders?
3. What is EnvironmentInjector used for?
Flashcards
Question
What is the Angular injector hierarchy?
Click to reveal answer
Answer
A tree of injectors mirroring the component tree. Each component has its own injector that inherits from its parent.
Question
What does a component-level provider create?
Click to reveal answer
Answer
A new instance scoped to that component and its children. Not shared with other components.
Question
What is EnvironmentInjector?
Click to reveal answer
Answer
Application-wide injector outside the component tree. Used for configuration, feature flags, and functional guards.
Revision Notes
Key Takeaways
- 1. Angular's DI is hierarchical — each component has its own injector
- 2. Component providers create scoped instances
- 3. viewProviders restrict access to the component's own view
- 4. EnvironmentInjector provides app-wide providers outside the component tree
Interview Tips
- • Explain the injector tree and how it mirrors the component tree
- • Be ready to describe when to use each provider scope
- • Mention EnvironmentInjector for functional patterns
Cheat Sheet
Hierarchical DI Cheat Sheet
Provider scopes:
// Root (app-wide singleton)
@Injectable({ providedIn: 'root' })
// Module
@Injectable({ providedIn: SomeModule })
// Component (per-component instance)
@Component({ providers: [Service] })
// Environment (outside component tree)
{ provide: TOKEN, useValue: value } // in app.config.ts
viewProviders vs providers:
providers— available to view + projected contentviewProviders— available only to the component's own view