下面的代码使用 runInInjectionContext 注入 ng-zorro-antd 的 NzPopoverDirective
private onHostViewChanged() {
this._viewInitialized$.pipe(take(1), takeUntil(this._destroyed)).subscribe(() => {
runInInjectionContext(this._environmentInjector, () => {
this._nzPopover = inject(NzPopoverDirective);
this.observeEvents();
});
});
}
运行时报错
Uncaught NullInjectorError: NullInjectorError: No provider for o!
如果注入的是注册在 root provider 的类型
runInInjectionContext(this._environmentInjector, () => {
this._notify = inject(NotifyService);
});
@Injectable({ providedIn: 'root' })
export class NotifyService { }
请问如何解决这个问题?
通过一篇讲解 angular 依赖注入的好文 Dependency Injection in Angular – everything you need to know 知道了原因
问题是 EnvironmentInjector 引起的
private readonly _environmentInjector = inject(EnvironmentInjector);
在 Component 级声明 providers: [NzPopoverDirective]
针对的是 Element Injector
Element Injector — registers dependencies defined in providers inside the @Component or @Directive decorators. These dependencies are available for the component and its children.
Environment Injector 是比 Element Injector 更高层的 injector
Environment Injector — child hierarchies of the environment injector are created whenever dynamically loaded components are created, such as with a router. In that case, the injector is available for components and its children. It is higher in the hierarchy than the element injector in the same component.
所以,针对 Element Injector 的 provider 对 Environment Injector 不起作用
解决方法很简单,将 EnvironmentInjector
换成 Injector
private readonly _injector = inject(Injector);
private onHostViewChanged() {
this._viewInitialized$.pipe(take(1), takeUntil(this._destroyed)).subscribe(() => {
runInInjectionContext(this._injector, () => {
this._nzPopover = this.createNzPopover();
this.observeEvents();
});
});
}
What is the injection context in Angular 16+
– dudu 4天前