在嵌套结构指令中找不到父服务

时间:2019-06-13 16:45:26

标签: angular angular2-directives angular-directive

我正在使用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> 

我希望可以通过DemoService实例访问父指令中的parentDemoService,但是收到以下错误:

错误 错误:StaticInjectorError(AppModule)[ParentDirective-> DemoService]: StaticInjectorError(平台:核心)[ParentDirective-> DemoService]: NullInjectorError:DemoService没有提供程序!

我已经将演示代码放在stackblitz上。

有人可以帮我吗? 谢谢。

P / s:我想为每个指令提供新的实例。这就是为什么我在父子指令中使用provider的原因

由于有些人不理解我的问题(我想可能不够清晰),所以我更新了2张图片来描述我的问题。

假设DemoService具有一个计数器变量,其父级变量从1开始,并且可以由子级结构指令增加。

这是我的预期结果:

Expected result

3 个答案:

答案 0 :(得分:0)

说明:

错误消息指出angular无法注入父指令所需的服务。您应该通过指定提供者详细信息来帮助angular识别所需的服务。有两种指定方法。

解决方案: 在app.module.ts中引入Control4 controller即可解决。

答案 1 :(得分:0)

要实现此目的,您需要重组整个应用程序。

创建一个具有两个服务ParentModuleShareService作为提供者的DemoService,并在此模块中声明,导出ParentDirective并将其导入RootModule

并在DemoService中提供ChildDirective

现在实例化DemoService中的ShareService并使该实例等于ParentDirective实例, 因此,您可以通过ParentDirective访问ChildDirective中的ShareService实例。

查看以下内容:stackblitz

答案 2 :(得分:0)

这是一个棘手的问题,所以我首先要说我对棱角还很陌生,并且还有很长的路要走。但是我喜欢学习,因此我尝试使用官方文档和示例来了解您的问题并为您实施解决方案。因此,请自行决定使用以下实现!

取决于您要确切执行的操作,应用程序需要对结构进行一些更改。据我所知,在组件级别提供服务会限制该组件的服务,并且不会实现您的目标。在这里,我为您提供了两种解决方案:

1-定义DemoService和一个ChildDemoService,该DemoService扩展'root'中的DemoService并将ChildDemoService注入到父子指令中,并注入仅DemoService插入子指令。这样,您将在两个组件中拥有两个childDemoService实例,但是这些实例将共享相同的状态,并且可以通过父指令和子指令进行编辑。您还将有一个console.log(),只有孩子可以访问(不确定是否需要此孩子)。

我已经在Stackblitz中更新了您的代码以反映这一点。我为您提供了有意义的{{1}},因此请不要忘记打开浏览器检查器!

有关更多信息,请参考Angular Official Documentation并尝试使用Their Example

2-创建一个单独的模块,该模块声明您的子指令和父指令,并在该模块中提供服务,以便只能通过这两个指令访问您的服务实例,并且这些指令本身可以在您希望它们出现的任何位置访问在应用中访问(取决于您的实现)

如果您有任何疑问或疑虑,请告诉我,因为这对我来说是一个有趣的问题。

干杯, 亚历克斯