将服务实例传播到对话框组件未按预期工作

cmx*_*mxl 8 dependency-injection angular-material angular

我在 stackblitz 上简单地复制了我想要实现的目标: https: //stackblitz.com/edit/angular-zb8kvg

我有一个组件(这里是 app.component),在该组件上声明了服务(MyService)。每次打开组件时,我都需要一个新的 MyService 实例,因此在我看来,该服务是在组件级别而不是在模块中声明的,这是正确的。

现在我想从此组件打开一个对话框(MatDialog -> TestComponent),它需要相同的服务实例。

我收到一个 StaticInjectorError,如控制台输出中所示。

如何在对话框中使用与调用组件相同的服务实例?

Luk*_*fer 20

我遇到了同样的问题,并找到了一个解决方案,允许以通常的方式将服务注入到对话框组件中。传递MatDialogConfig给该方法的属性有一个使用以下文档MatDialog.open调用的属性:viewContainerRef

附加组件应该位于 Angular 的逻辑组件树中。这会影响可用于注入的内容以及对话框内实例化组件的更改检测顺序。这不会影响对话框内容的呈现位置。

只需传递电流ViewContainerRef(注入到主机组件中),它就会按预期工作:

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
  providers: [MyService]
})
export class AppComponent {
  constructor(public dialog: MatDialog, private viewContainerRef: ViewContainerRef) {}

  open() {
    this.dialog.open(DialogComponent, { viewContainerRef: this.viewContainerRef });
  }
}

@Component({
  template: "<h1>DialogComponent</h1>"
})
export class DialogComponent {
  constructor(private myService: MyService) { }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*iro 3

这是因为该对话框,即使是从您的 app.component请求的,也不是它的子项。如果您检查对话框的 DOM 元素,您可以看到这一点:对话框被附加到 的根元素的某个位置body,作为 Angular 应用程序的根元素的同级元素。

因此,依赖项注入正在按预期工作,只是服务的范围不涵盖对话框。

建议的解决方案:您可以在MatDialogConfig的 param中传递数据MatDialog.open,该参数有一个 data 字段。

该数据可以通过多种方式使用:

  • 您可以从调用对话框的组件向其中传递回调,对话框可以调用该回调。回调将有权访问注入到调用对话框的组件中的服务。
  • 您可以只从调用对话框的组件中传递对服务实例的引用,因此对话框中的组件基本上具有完整的服务实例

示例:https: //material.angular.io/components/dialog/examples(参见第一个示例的 TS 部分)