Skip to content

Commit 6892595

Browse files
committed
feat(dialog): Add dialog support
1 parent 10df1d6 commit 6892595

File tree

14 files changed

+236
-5
lines changed

14 files changed

+236
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"scripts": {
66
"ng": "ng",
77
"prestart": "ng build",
8-
"start": "ng serve",
8+
"start": "ng serve --open",
99
"build": "ng build abstract --prod",
1010
"watch:lib": "ng build abstract --watch",
1111
"test": "ng test abstract",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {OverlayRef} from '@angular/cdk/overlay';
2+
import {Observable, Subject} from 'rxjs';
3+
import {takeUntil} from 'rxjs/operators';
4+
5+
import {INgxAbsDialogConfig} from './ngx-abs-dialog.service';
6+
7+
export class NgxAbsDialogRef<T, R = undefined> {
8+
private onClose = new Subject<R>();
9+
10+
constructor(
11+
private overlayRef: OverlayRef,
12+
readonly config: INgxAbsDialogConfig<T>
13+
) {
14+
if (config.backdropClickClose) {
15+
this.backdropClick()
16+
.pipe(takeUntil(this.onClose))
17+
.subscribe(() => {
18+
this.close();
19+
});
20+
}
21+
}
22+
23+
afterClosed(): Observable<R> {
24+
return this.onClose.asObservable();
25+
}
26+
27+
backdropClick(): Observable<MouseEvent> {
28+
return this.overlayRef.backdropClick();
29+
}
30+
31+
keydownEvents(): Observable<KeyboardEvent> {
32+
return this.overlayRef.keydownEvents();
33+
}
34+
35+
close(modalResult?: R): void {
36+
this.overlayRef.dispose();
37+
this.onClose.next(modalResult);
38+
this.onClose.complete();
39+
}
40+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {Directive, HostListener, Input, OnInit} from '@angular/core';
2+
import {NgxAbsDialogRef} from './NgxAbsDialogRef';
3+
4+
@Directive({
5+
selector: '[absDialogClose]',
6+
exportAs: 'absDialogClose'
7+
})
8+
export class NgxAbsDialogCloseDirective implements OnInit {
9+
@Input() absDialogClose: any;
10+
11+
constructor(private ngxAbsDialogRef: NgxAbsDialogRef<any>) {
12+
}
13+
14+
@HostListener('click') close(): void {
15+
this.ngxAbsDialogRef.close(this.absDialogClose);
16+
}
17+
18+
@HostListener('document:keydown.escape') escClose(): void {
19+
this.close();
20+
}
21+
22+
ngOnInit(): void {
23+
}
24+
25+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {ComponentType, GlobalPositionStrategy, Overlay, OverlayConfig} from '@angular/cdk/overlay';
2+
import {ComponentPortal} from '@angular/cdk/portal';
3+
import {Injectable, Injector, StaticProvider} from '@angular/core';
4+
5+
import {NgxAbsDialogRef} from './NgxAbsDialogRef';
6+
import {NGX_ABS_DIALOG_DATA} from './tokens';
7+
8+
export interface INgxAbsDialogConfig<T = any> extends Omit<OverlayConfig, 'positionStrategy'> {
9+
data?: T;
10+
backdropClickClose?: boolean;
11+
}
12+
13+
@Injectable()
14+
export class NgxAbsDialog {
15+
16+
constructor(
17+
private overlay: Overlay,
18+
private injector: Injector
19+
) {
20+
}
21+
22+
static createConfig<T>(config?: INgxAbsDialogConfig<T>): INgxAbsDialogConfig<T> {
23+
return {
24+
backdropClickClose: true,
25+
hasBackdrop: true,
26+
disposeOnNavigation: false,
27+
...config
28+
};
29+
}
30+
31+
open<T, R = any>(
32+
cmp: ComponentType<any>,
33+
config?: INgxAbsDialogConfig<T>,
34+
providers?: StaticProvider[]
35+
): NgxAbsDialogRef<T, R> {
36+
const configOptions = NgxAbsDialog.createConfig(config);
37+
const overlay = this.overlay.create(configOptions);
38+
const position = new GlobalPositionStrategy();
39+
overlay.updatePositionStrategy(position);
40+
position.centerHorizontally();
41+
position.centerVertically();
42+
const modalRef = new NgxAbsDialogRef<T, R>(overlay, configOptions);
43+
const cmpPortal = new ComponentPortal(
44+
cmp, null, Injector.create({
45+
providers: [
46+
{provide: NGX_ABS_DIALOG_DATA, useValue: config?.data},
47+
{provide: NgxAbsDialogRef, useValue: modalRef},
48+
...(providers || [])
49+
],
50+
parent: this.injector
51+
})
52+
);
53+
overlay.attach(cmpPortal);
54+
return modalRef;
55+
}
56+
57+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {OverlayModule} from '@angular/cdk/overlay';
2+
import {CommonModule} from '@angular/common';
3+
import {NgModule} from '@angular/core';
4+
5+
import {NgxAbsDialogCloseDirective} from './ngx-abs-dialog-close.directive';
6+
import {NgxAbsDialog} from './ngx-abs-dialog.service';
7+
8+
9+
@NgModule({
10+
declarations: [
11+
NgxAbsDialogCloseDirective
12+
],
13+
imports: [
14+
CommonModule,
15+
OverlayModule
16+
],
17+
providers: [
18+
NgxAbsDialog,
19+
],
20+
exports: [
21+
NgxAbsDialogCloseDirective,
22+
]
23+
})
24+
export class NgxAbstractDialogModule {
25+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import {InjectionToken} from '@angular/core';
2+
3+
export const NGX_ABS_DIALOG_DATA = new InjectionToken('NGX Abstract dialog modal data');
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './ngx-abstract-dialog/ngx-abstract-dialog.module';
2+
export * from './ngx-abstract-dialog/ngx-abs-dialog-close.directive';
3+
export * from './ngx-abstract-dialog/ngx-abs-dialog.service';
4+
export * from './ngx-abstract-dialog/tokens';

src/app/app.component.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ <h1>Hello world</h1>
22
<button (click)="setTitle('Hey')">
33
Change title
44
</button>
5+
6+
<button (click)="openDialog()">
7+
Open Dialog
8+
</button>

src/app/app.component.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
1-
import {Component} from '@angular/core';
1+
import {ChangeDetectionStrategy, Component} from '@angular/core';
22
import {AbsPage} from '@wanoo21/ngx-abstract';
3+
import {NgxAbsDialog} from '@wanoo21/ngx-abstract/dialog';
4+
5+
import {DialogTestComponent} from './dialog-test/dialog-test.component';
36

47
@Component({
58
selector: 'app-root',
69
templateUrl: './app.component.html',
7-
styleUrls: ['./app.component.css']
10+
styleUrls: ['./app.component.css'],
11+
changeDetection: ChangeDetectionStrategy.OnPush
812
})
913
export class AppComponent extends AbsPage {
10-
constructor() {
14+
constructor(readonly ngxAbsDialog: NgxAbsDialog) {
1115
super('My super title', 'My Super Description');
1216
}
17+
18+
openDialog(): void {
19+
this.ngxAbsDialog.open(DialogTestComponent,
20+
{data: {foo: 'bar'}, backdropClickClose: false}
21+
).afterClosed().subscribe(value => {
22+
console.log(value);
23+
});
24+
}
1325
}

0 commit comments

Comments
 (0)