下面的 Directive 实现,运行时会报错 NullInjectorError: No provider for t!
@Directive({
providers: [NzDropDownDirective]
})
export abstract class BaseDropdownContainer implements AfterViewInit, OnDestroy {
dropdownDirective?: NzDropDownDirective;
constructor(protected injector: Injector) { }
ngAfterViewInit(): void {
runInInjectionContext(this.injector, () => {
this.createDropdownDirective();
});
}
protected createDropdownDirective(): this {
this.dropdownDirective = inject(NzDropDownDirective);
this.dropdownDirective.ngAfterViewInit();
return this;
}
}
请问如何解决这个问题?
错误发生在下面的代码
this.dropdownDirective = inject(NzDropDownDirective);
浏览器控制台报错截图
通过下面的代码排查测试,NzDropDownDirective 的构造函数的参数类型都能正常 inject,报错的依然是 inject(NzDropDownDirective)
runInInjectionContext(this.injector, () => {
inject(NzConfigService);
inject(Overlay);
inject(ElementRef);
inject(Renderer2);
inject(ViewContainerRef);
inject(Platform);
inject(NzDropDownDirective);
});
新建一个 angular 19 项目,在 AppComponent 用同样的代码测试,没出现这个问题,可以正常 inject
@Component({
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css',
providers: [NzDropDownDirective]
})
export class AppComponent {
title = 'angular-sample';
constructor(protected injector: Injector) { }
ngAfterViewInit(): void {
runInInjectionContext(this.injector, () => {
inject(NzDropDownDirective);
});
}
}
providers: [NzDropDownDirective]
加错地方了,应该加在使用 Directive 的 Component 上
这里的 BaseDropdownContainer 是一个抽象类,实际使用的 Directive 是 DropdownContainerDirective,加在这个 Directive 中也不行
@Directive({
selector: '[cnbDropdownContainer]',
exportAs: 'cnbDropdownContainer',
standalone: true
})
export class DropdownContainerDirective<C extends BaseDropdownContainer>
implements OnInit, OnDestroy {
}
要加在使用 DropdownContainerDirective 的 Component 中
@Component({
selector: 'cnb-post-body-editor-switcher',
template: `
<div [class.disabled]="isSwitching">
<div class="d-inline-block"
cnbDropdownContainer
[importComponent]="importDropdown"
(componentChange)="onDropdownComponentChange($event)">
<button class="cnb-button-secondary dropdown-toggle"
id="editor-switcher"
*ngIf="currentEditorId$ | async | editorViewModel as editor">编辑器: {{editor.name}}</button>
</div>
</div>
`,
providers: [RxHelper, NzDropDownDirective],
standalone: false
})
参考资料:Cracking Angular DI: The Hidden Layers of Injectors
– dudu 2个月前