The Angular Material source code for Dialog
shows that an Injector
is used to instantiate the Component to be displayed in the Dialog. This approach breaks circular dependencies.
Therefore, the circular dependency warning appears to be a false positive.
Circular dependency warnings may be disabled by updating angular.json. Unfortunately, this option is not available per file.
angular.json
....
"defaults": {
....
"build": {
"showCircularDependencies": false
}
}
Workaround
The solution below allows for nested calls where a Dialog
of component type DialogYesNoComponent
may open a Dialog
of component type DialogWarningComponent
and vice versa.
Example
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) {
...
}
}
DialogService
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) { }
}
DialogWarningComponent
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) { }
}