Last active
February 28, 2024 21:26
-
-
Save mfp22/479a6860510286e69d9cb7ea3a448d5e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Component, | |
Input, | |
OnChanges, | |
SimpleChanges, | |
OnDestroy, | |
} from '@angular/core'; | |
import { | |
MatDialogRef, | |
MatDialogConfig, | |
MatDialog, | |
} from '@angular/material/dialog'; | |
import { Observable } from 'rxjs'; | |
// Separate files | |
export interface AppDialogState { | |
[index: string]: Observable<any>; | |
} | |
export interface AppDialogActions { | |
[index: string]: Function; | |
} | |
@Component({ | |
selector: 'app-dialog-content-component', | |
template: '', | |
}) | |
export class DialogContentComponent { | |
state: AppDialogState; | |
actions: AppDialogActions; | |
} | |
@Component({ | |
selector: 'app-dialog', | |
template: '', | |
}) | |
export class AppDialogComponent | |
implements OnChanges, OnDestroy, DialogContentComponent { | |
// Can't find a type that this.dialog.open likes without importing something obscure | |
@Input() component: any; | |
@Input() state: AppDialogState = {}; | |
@Input() actions: AppDialogActions = {}; | |
@Input() open = false; | |
@Input() config: MatDialogConfig; | |
dialogRef: MatDialogRef<any>; | |
constructor(public dialog: MatDialog) {} | |
ngOnChanges(changes: SimpleChanges) { | |
if (changes.open) { | |
this.applyDialogState(changes.open.currentValue); | |
} | |
} | |
ngOnDestroy() { | |
// setTimeout because applyDialogState is sometimes on a timeout | |
// when this runs and can reopen the dialog | |
// after this component is already destroyed. | |
setTimeout(() => this.closeDialog()); | |
} | |
applyDialogState = (shouldBeOpen: boolean) => { | |
setTimeout(() => { | |
// Change detection console error without this | |
const isOpen = !!this.dialogRef; | |
if (!isOpen && shouldBeOpen) { | |
this.openDialog(); | |
} else if (isOpen && !shouldBeOpen) { | |
this.closeDialog(); | |
} | |
}); | |
}; | |
openDialog() { | |
this.dialogRef = this.dialog.open(this.component, this.config); | |
this.dialogRef.componentInstance.state = this.state; | |
this.dialogRef.componentInstance.actions = this.actions; | |
} | |
closeDialog() { | |
if (this.dialogRef) { | |
this.dialogRef.close(); | |
} | |
this.dialogRef = undefined; | |
} | |
} |
Obviously the problem was on my side...
Didn't think of referencing an ng-template.
It works flawlessly now!
Just for the sake of clarity, if anyone is dumb enough to be in my same shoes, it's used like this:
<app-dialog [component]="dialogComponent" [open]="open$ | async"></app-dialog>
<ng-template #dialogComponent> ... something ... </ng-template>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can i ask you a simple usage explanation, please?
When i write imperatively i can do something like this:
dialog.open(TestComponent)
where TestComponent is not an instance but it's used as a type.
How can i do the same with this dialog?
If i understand it correctly i should do something along this:
<app-dialog [component]="TestComponent" ...></app-dialog>
but it complains that TestComponent is not a property of the component, while if i try to add a property it obviously fails at runtime because the instance is undefined.
What i'm doing wrong?