我的 Angular 8 应用程序使用一个服务类,该服务类包装 Angular Material 对话框实现并基于许多不同的组件类型呈现对话框。这是它的简化版本:
@Injectable()
export class MyService {
renderDialogTypeOne() {
// implementation here calls
// matDialog.open(TypeOne)
}
renderDialogTypeTwo() {
// implementation here calls
// matDialog.open(TypeTwo)
}
}
由于此服务类引用它呈现的类型,因此它对它们具有依赖性。但是,其中一种呈现的类型(下面的 TypeTwo
)也将上述服务注入(inject)到其构造函数中,以便它可以启动自己的 TypeOne
对话框:
export class TypeOne {
}
export class TypeTwo {
contructor(private service: MyService) { }
showNestedDialog() {
this.service.renderDialogTypeOne();
}
}
因此,服务类和 TypeTwo
之间似乎存在循环依赖关系。我知道我可以通过将服务类分成多个部分并仅引用给定上下文中所需的部分来解决此问题,但纯粹拆分一个类来解决编译器警告似乎并不正确。
这真的是循环依赖吗?如果是这样,那么在许多其他场景中,两个实体具有先有鸡还是先有蛋的关系,不也存在同样的问题吗?
除了禁用 Angular 的循环依赖警告之外,还有其他合理的解决方案吗?
最佳答案
Dialog
的 Angular Material 源代码显示Injector
用于实例化要在对话框中显示的组件。 This approach breaks circular dependencies .
因此,循环依赖警告似乎是误报。
可以通过更新 angular.json 来禁用循环依赖警告。不幸的是,这个选项不适用于每个文件。
Angular .json
....
"defaults": {
....
"build": {
"showCircularDependencies": false
}
}
解决方法
下面的解决方案允许嵌套调用,其中 Dialog
组件类型 DialogYesNoComponent
可以打开Dialog
组件类型 DialogWarningComponent
反之亦然。
示例
import { DialogService, DialogYesNoComponent, DialogWarningComponent } from '...'
export class TypeOne {
constructor(private dialog_service: DialogService) { }
showYesNoDialog() {
const dialog_question = "Would you like to continue?";
const dialog_ref: MatDialogRef<DialogYesNoComponent> =
this.dialog_service.open_yes_no_dialog({
question: dialog_question,
title: 'Confirm', height: '300px' })
dialog_ref.afterClosed().subscribe(
(choice: 'yes' | 'no') => {
if (choice === 'yes') {
// Continue
} else {
// Open Nested Dialog
this.showWarningDialog("Stopping the program.");
}
}
)
}
showWarningDialog(warning: String) {
...
}
}
对话服务
import { ElementRef, Injectable } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material';
import { DialogWarningComponent } from './dialog-warning/dialog-warning.component';
import { DialogYesNoComponent } from './dialog-yes-no/dialog-yes-no.component';
@Injectable()
export class DialogService {
constructor(public dialog: MatDialog) { }
public open_yes_no_dialog({ question, title = 'Confirm', yes_button_first = true,
has_backdrop = false, height = '250px', width = '350px' }:
{
question: string, title?: string, yes_button_first?: boolean, has_backdrop?: boolean,
height?: string, width?: string
}): MatDialogRef<DialogYesNoComponent> {
const dialog_ref = this.dialog.open(DialogYesNoComponent, {
autoFocus: true,
backdropClass: 'cdk-overlay-transparent-backdrop',
closeOnNavigation: true,
disableClose: false,
hasBackdrop: has_backdrop,
height: height,
width: width,
data: { question: question, title: title, yes_button_first: yes_button_first }
})
return dialog_ref
}
public open_warning_dialog() {
{ warning, title = 'Warning',
has_backdrop = false, height = '250px', width = '350px' }:
{
warning: string, title?: string, has_backdrop?: boolean,
height?: string, width?: string
}): MatDialogRef<DialogWarningComponent> {
const dialog_ref = this.dialog.open(DialogWarningComponent, {
autoFocus: true,
backdropClass: 'cdk-overlay-transparent-backdrop',
closeOnNavigation: true,
disableClose: false,
hasBackdrop: has_backdrop,
height: height,
width: width,
data: { warning: warning, title: title }
})
return dialog_ref
}
}
DialogYesNoComponent
import { Component, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
export interface YesNoDialogOptions {
question: string
title: string
yes_button_first: boolean
}
@Component({
selector: 'dialog-yes-no',
templateUrl: './dialog-yes-no.component.html',
styleUrls: ['./dialog-yes-no.component.css']
})
export class DialogYesNoComponent {
constructor(public dialog_ref: MatDialogRef<DialogYesNoComponent>,
@Inject(MAT_DIALOG_DATA) public options: YesNoDialogOptions) { }
}
对话框警告组件
import { Component, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
export interface WarningDialogOptions {
warning: string
title: string
}
@Component({
selector: 'dialog-warning',
templateUrl: './dialog-warning.component.html',
styleUrls: ['./dialog-warning.component.css']
})
export class DialogWarningComponent {
constructor(public dialog_ref: MatDialogRef<DialogWarningComponent>,
@Inject(MAT_DIALOG_DATA) public options: WarningDialogOptions) { }
}
关于 Angular CLI : False positive circular dependency warning for nested Material Dialogs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57512174/