在嵌套结构指令中找不到父服务
Posted
技术标签:
【中文标题】在嵌套结构指令中找不到父服务【英文标题】:Cannot find parent service in nested structural directive 【发布时间】:2019-10-28 07:45:19 【问题描述】:我正在使用 Angular 8 来构建我的小应用程序。 在我的应用程序中,我有 2 个结构指令:
parent.directive.ts
:
@Directive(
selector: '[parent]',
providers: [
DemoService
]
)
export class ParentDirective implements OnInit
public constructor(protected viewContainerRef: ViewContainerRef,
protected templateRef: TemplateRef<any>,
public demoService: DemoService)
public ngOnInit()
this.demoService
.name = 'parent';
this.viewContainerRef.createEmbeddedView(this.templateRef);
child.directive.ts:
@Directive(
selector: '[child]',
providers: [
DemoService
]
)
export class ChildDirective implements OnInit
public constructor(protected viewContainerRef: ViewContainerRef,
protected templateRef: TemplateRef<any>,
public demoService: DemoService,
@SkipSelf() public parentDemoService: DemoService)
public ngOnInit()
this.demoService
.name = 'parent';
console.log(this.parentDemoService.name);
我的 2 个指令都初始化了一个DemoService
,但是,在child.directive.ts
中,我还想访问DemoService
中的parent.directive.ts
。
因此,在child.directive.ts
,我将DI声明如下:
public constructor(protected viewContainerRef: ViewContainerRef,
protected templateRef: TemplateRef<any>,
public demoService: DemoService,
@SkipSelf() public parentDemoService: DemoService)
这是我在html页面中使用的:
<div *parent>
<div>Inside parent</div>
<div *child>
<div>Inside child</div>
</div>
<div *parent>
<div>Inside parent parent</div>
<div *child>
<div>Inside child</div>
</div>
</div>
</div>
</div>
</div>
我希望我可以通过parentDemoService
实例访问父指令中的DemoService
,但我收到以下错误:
错误 错误:StaticInjectorError(AppModule)[ParentDirective -> DemoService]: StaticInjectorError(平台:核心)[ParentDirective -> DemoService]: NullInjectorError:没有 DemoService 的提供者!
我已经把我的演示代码放在stackblitz上。
谁能帮我解决这个问题? 谢谢。
P/s : 我想为每个指令提供新的实例。这就是我在父子指令中使用提供者的原因
因为有些人不理解我的问题(也许我觉得不够清楚),所以我更新了 2 张图片来描述我的问题。
比方说,DemoService
有一个计数器变量,在父级中从 1 开始,可以通过子结构指令增加。
这是我的预期结果:
【问题讨论】:
【参考方案1】:解释:
错误消息表明 Angular 无法注入父指令所需的服务。您应该通过指定提供者详细信息来帮助 Angular 识别所需的服务。有几种指定方式。
解决方案:
在 app.module.ts 中引入providers: [DemoService]
即可解析。
【讨论】:
其实我想为每个指令提供新的实例。这就是我在parent
和child
指令中使用提供程序的原因。【参考方案2】:
为此,您需要重组整个应用程序。
创建一个ParentModule
,其中两个服务ShareService
和DemoService
作为提供者并声明,在此模块中导出ParentDirective
并将其导入RootModule
。
并在ChildDirective
中提供DemoService
。
现在在ShareService
中实例化DemoService
并使此实例等于ParentDirective
实例,
所以你可以通过ShareService
访问ChildDirective
中的这个ParentDirective
实例。
看看这个:stackblitz
【讨论】:
【参考方案3】:这是一个棘手的问题,所以我首先要说我对 Angular 还很陌生,还有很长的路要走。但我喜欢学习,所以我尝试了解您的问题并使用官方文档和示例为您实施解决方案。因此,请自行决定使用以下实现!
根据您想要做什么,应用程序需要对结构进行一些更改。据我所知,在组件级别提供服务会将服务限制在该组件上,并且不会让您实现目标。这里我有两个解决方案给你:
1- 定义 DemoService
和 ChildDemoService
扩展 'root'
中的 DemoService
并将您的 DemoService
注入父指令和子指令,并将 ChildDemoService
注入您的子指令。这样,您将在两个组件中拥有两个 DemoService
实例,但这些实例将共享相同的状态,并且可以通过父指令和子指令进行编辑。您还将拥有一个只有孩子可以访问的childDemoService
(不确定您是否需要这个)。
我已更新您在 Stackblitz 中的代码以反映这一点。我为您添加了有意义的console.log()
s,所以不要忘记打开您的浏览器检查器!
有关更多信息,请参阅Angular Official Documentation 并与Their Example 一起玩。
2- 创建一个单独的模块来声明您的子指令和父指令并在该模块中提供您的服务,以便您的服务实例只能通过这两个指令访问,并且指令本身可以在您希望它们的任何地方访问在应用程序中访问(取决于您的实现)
如果您有任何问题或疑虑,请告诉我,因为这对我来说是一个有趣的问题。
干杯, 亚历克斯
【讨论】:
实际上我将DemoService
从父母注入到孩子,因为我希望孩子只能访问属于其父母的信息。如果parent
在parent
旁边。 2 个父母和其孩子的 parentService 的服务生命周期必须不同。
我不太明白,请您详细说明一下?
@Redplane 是的,您可以通过创建parentModule
来实现这一点。检查我的回答,如果您需要进一步的帮助,请告诉我。
@Alex,我在 stackblitz 上尝试了您的解决方案。其实这不是我预期的结果。我已经制作了 2 张关于您的解决方案和预期结果的图片。这是您的结果 i.imgur.com/Ou4kNKN.png ,这是预期的结果:i.imgur.com/PDXq5f0.png【参考方案4】:
我遇到了同样的问题,因为我试图通过结构指令 (*) 提供程序提供新的服务实例。这是角度限制。 我的解决方案是在与 *parent 相同的级别上创建新的 notstructural 指令来为嵌套指令提供服务。
<div *parent parentToProvideService>
<div>Inside parent</div>
<div *child>
<div>Inside child</div>
</div>
</div>
@Directive(
selector: '[parentToProvideService]',
providers: [
DemoService
]
)
export class ParentToProvideServiceDirective implements OnInit
public constructor(public demoService: DemoService)
public ngOnInit()
// some code
【讨论】:
以上是关于在嵌套结构指令中找不到父服务的主要内容,如果未能解决你的问题,请参考以下文章
在 Android Studio 中找不到“填充父级”[重复]