All quizzesMedium
Hierarchical Injectors
Preview — 3 of 10 questions
When should you use InjectionToken instead of a class as an injection token?
javascript
import { InjectionToken } from '@angular/core';
// Configuration interface (erased at runtime)
export interface AppConfig {
apiUrl: string;
featureFlags: Record<string, boolean>;
}
// Runtime token with type parameter
export const APP_CONFIG = new InjectionToken<AppConfig>('app.config', {
providedIn: 'root',
factory: () => ({
apiUrl: 'https://api.example.com',
featureFlags: { newDashboard: true },
}),
});
// Usage in service
@Injectable({ providedIn: 'root' })
export class ApiService {
private config = inject(APP_CONFIG);
fetchData() {
return fetch(this.config.apiUrl + '/data');
}
}AWhen you need to inject multiple instances of the same class
BWhen you want the service to be scoped to a single component
CWhen the value to inject is a primitive, interface, or object literal — since TypeScript interfaces are erased at runtime and can't serve as tokens
DWhen the service has no constructor dependencies
What does multi: true do in a provider configuration?
javascript
export const VALIDATORS = new InjectionToken<Validator[]>('VALIDATORS');
// Multiple places can provide to the same token
const coreProviders = [
{ provide: VALIDATORS, useClass: RequiredValidator, multi: true },
{ provide: VALIDATORS, useClass: EmailValidator, multi: true },
];
const featureProviders = [
{ provide: VALIDATORS, useClass: PasswordStrengthValidator, multi: true },
];
// The injected value is [RequiredValidator, EmailValidator, PasswordStrengthValidator]
@Injectable()
class FormService {
validators = inject(VALIDATORS); // Validator[]
}AIt creates a new instance for every injection
BIt makes the token available in child injectors automatically
CIt allows multiple providers for the same token — the injected value is an array of all provided values
DIt enables the service to be provided in multiple NgModules simultaneously
What is APP_INITIALIZER used for?
javascript
// app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
{
provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) => () => configService.loadConfig(),
deps: [ConfigService],
multi: true,
},
{
provide: APP_INITIALIZER,
useFactory: (authService: AuthService) => () => authService.refreshSession(),
deps: [AuthService],
multi: true,
},
],
};
@Injectable({ providedIn: 'root' })
class ConfigService {
config!: AppConfig;
loadConfig(): Promise<void> {
return fetch('/assets/config.json')
.then(r => r.json())
.then(c => { this.config = c; });
}
}ATo run code before the first component renders, optionally delaying bootstrap until async operations complete
BTo initialize component inputs before ngOnInit
CTo set up the Angular testing environment
DTo lazily load a module before routing starts
Sign up free to play
Answer all 10 questions (7 more), see explanations for every answer, and track your score.