Angular CLI : False positive circular dependency warning for nested Material Dialogs?

标签 angular typescript angular-material angular-cli circular-dependency

我的 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/

相关文章:

javascript - 有没有办法将工作 HTML 页面用作 Angular 5/6 组件?

angular - 有没有办法为 swagger ui 的深度链接片段添加前缀?

javascript - Typescript - 动态扩展接口(interface)

javascript - 使用 TypeScript 自定义 knockout 验证规则

angular - 如何防止 Angular/material mat-menu 在按键导航(选项卡)上关闭?

css - 如何用 Angular 形 Material 制作带内边框的 table

javascript - 是否可以使用 TypeScript 将 HTML 文件作为字符串导入?

typescript - 使用 typescript 在 angular2 中导入库的最佳方法

visual-studio-2013 - VS2013 不自动将 Typescript 生成的 Javascript 添加到项目中

angular - 错误 : Cannot find module '@angular-devkit/schematics' and Cannot find module '@angular-devkit/schematics'