Last active
March 5, 2020 15:27
-
-
Save l0co/0e2c9cb217ae86ba3e1ef9e1f87653c2 to your computer and use it in GitHub Desktop.
Angular material dialog component.
This file contains hidden or 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
<div class="mat-card-dialog"> | |
<h2 mat-dialog-title class="mat-card-dialog-title" *ngIf="title">{{title}}</h2> | |
<mat-icon mat-dialog-close class="mat-card-dialog-close pointer">close</mat-icon> | |
<ng-content></ng-content> | |
</div> |
This file contains hidden or 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 {AfterViewInit, Component, ContentChild, Input, OnInit} from '@angular/core'; | |
import {CardDialogService} from "../services/card-dialog.service"; | |
/** | |
* Angular material dialog component. | |
* | |
* ## Usage in template | |
* | |
* Put your component into `<app-card-dialog>` component, marking it with `#dialogComponent`. | |
* | |
* ```html | |
* <ng-template #myTemplate let-data> <!-- Use own ID and let-data if you want use custom data --> | |
* <app-card-dialog> <!-- This component is required as a top component --> | |
* <app-my-component <!-- This component is whatever one --> | |
* [myattr1]="data.attr1" <!-- You can set attributes using custom data (requires: let-data) --> | |
* [myattr2]="attr2" <!-- Or in a standard way from the parent component --> | |
* #dialogComponent> <!-- #dialogComponent is required to be set here (!) --> | |
* </app-my-component> | |
* </app-card-dialog> | |
* </ng-template> | |
* ``` | |
* | |
* ## Usage in (parent) component | |
* | |
* ```typescript | |
* class MyComponent { | |
* | |
* @ViewChild('myTemplate') myTemplate: TemplateRef<any>; | |
* attr2: string = 'value of attribute 2'; | |
* | |
* constructor(private cardDialog: CardDialogService) {} | |
* | |
* openDialog() { | |
* this.cardDialog.open<MyComponent>(this.myTemplate, {attr1: 'value of attribute 1'}).subscribe(component => { | |
* // here you have access to MyComponent instance as well (what's almost impossible for angular when it's inside ng-template) | |
* }); | |
* } | |
* | |
* closeDialog() { | |
* this.cardDialog.close(); | |
* } | |
* | |
* } | |
* ``` | |
*/ | |
@Component({ | |
selector: 'app-card-dialog', | |
templateUrl: './card-dialog.component.html', | |
styleUrls: ['./card-dialog.component.scss'] | |
}) | |
export class CardDialogComponent<C = any> implements OnInit, AfterViewInit { | |
@Input('title') title?: string; | |
@ContentChild('dialogComponent') component: C; | |
constructor( | |
private cardDialogService: CardDialogService, | |
) { } | |
ngOnInit(): void { | |
} | |
ngAfterViewInit(): void { | |
this.cardDialogService.onComponentReady(this.component); | |
} | |
} |
This file contains hidden or 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 {Injectable, TemplateRef} from '@angular/core'; | |
import {MatDialog, MatDialogConfig} from "@angular/material/dialog"; | |
import {MatDialogRef} from "@angular/material/dialog/dialog-ref"; | |
import {Loggable} from "../../../classes/loggable.class"; | |
import {NGXLogger} from "ngx-logger"; | |
import {Observable, Subject} from "rxjs"; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class CardDialogService extends Loggable { | |
protected dialogs: {dialog: MatDialogRef<any>, component: Subject<any>, current?: any}[] = []; | |
constructor( | |
log: NGXLogger, | |
private matDialog: MatDialog, | |
) { | |
super(log); | |
} | |
open<C>(dialogTemplate: TemplateRef<any>, data?: any, config?: MatDialogConfig): Observable<C> { | |
this.log.debug('Opening dialog', this.dialogs.length); | |
let single = new Subject<C>(); | |
let dialog = { | |
dialog: this.matDialog.open(dialogTemplate, Object.assign({ | |
panelClass: 'mat-card-panel-container', | |
maxHeight: '90vh', | |
data, | |
}, | |
config || {}) | |
), | |
component: single | |
}; | |
dialog.dialog.afterClosed().subscribe(it => { | |
this.onClose(); | |
}); | |
this.dialogs.push(dialog); | |
return single; | |
} | |
close() { | |
this.dialogs[this.dialogs.length-1].dialog.close(); | |
} | |
protected onClose() { | |
this.dialogs.pop(); | |
this.log.debug('Closing dialog', this.dialogs.length); | |
} | |
onComponentReady(component: any) { | |
this.log.debug('Registering component for current dialog:', component.constructor.name); | |
this.dialogs[this.dialogs.length-1].component.next(component); | |
this.dialogs[this.dialogs.length-1].component.complete(); | |
this.dialogs[this.dialogs.length-1].current = component; | |
} | |
get currentComponent(): any { | |
return this.dialogs[this.dialogs.length-1]?.current; | |
} | |
get currentDialogRef(): MatDialogRef<any> { | |
return this.dialogs[this.dialogs.length-1]?.dialog; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment