Skip to content

Commit 8456cba

Browse files
authored
feat: 模态弹窗添加最大化和退出最大化功能 (#320)
1 parent e828814 commit 8456cba

18 files changed

+313
-122
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<d-button (click)="openDialog()">open dialog</d-button>
2+
<d-button bsStyle="common" (click)="openDialog('standard', false)">open dialog without animation</d-button>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Component } from '@angular/core';
2+
import { DialogService } from 'ng-devui/modal';
3+
import { ModalTestComponent } from '../modal-test.component';
4+
5+
@Component({
6+
selector: 'd-maximize',
7+
templateUrl: './maximize.component.html',
8+
})
9+
export class MaximizeComponent {
10+
config = {
11+
id: 'dialog-service',
12+
width: '346px',
13+
maxHeight: '600px',
14+
title: 'Start Snapshot Version',
15+
content: ModalTestComponent,
16+
backdropCloseable: true,
17+
onClose: () => console.log('on dialog closed'),
18+
data: {
19+
name: 'Tom',
20+
age: 10,
21+
address: 'Chengdu',
22+
},
23+
};
24+
25+
constructor(private dialogService: DialogService) {}
26+
27+
openDialog(dialogtype?: string, showAnimation?: boolean) {
28+
const results = this.dialogService.open({
29+
...this.config,
30+
showMaximizeBtn: true,
31+
dialogtype: dialogtype,
32+
showAnimation: showAnimation,
33+
buttons: [
34+
{
35+
cssClass: 'primary',
36+
text: 'Ok',
37+
disabled: false,
38+
handler: ($event: Event) => {
39+
results.modalInstance.hide();
40+
},
41+
},
42+
{
43+
id: 'btn-cancel',
44+
cssClass: 'common',
45+
text: 'Cancel',
46+
handler: ($event: Event) => {
47+
results.modalInstance.hide();
48+
},
49+
},
50+
],
51+
});
52+
console.log(results.modalContentInstance);
53+
}
54+
}

devui/modal/demo/modal-demo.component.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
<d-basic demo></d-basic>
88
</d-codebox>
99
</div>
10+
<div class="devui-demo-example" [dAnchor]="'maximize-dialog'">
11+
<div class="devui-demo-title">{{ 'components.modal.maximizeDemo.title' | translate }}</div>
12+
<div class="devui-demo-text">{{ 'components.modal.maximizeDemo.description' | translate }}</div>
13+
<d-codebox id="basic" [sourceData]="maximizeSource">
14+
<d-maximize demo></d-maximize>
15+
</d-codebox>
16+
</div>
1017
<div class="devui-demo-example" [dAnchor]="'intercept-dialog-closed'">
1118
<div class="devui-demo-title">{{ 'components.modal.hideDemo.title' | translate }}</div>
1219
<div class="devui-demo-text">{{ 'components.modal.hideDemo.description' | translate }}</div>

devui/modal/demo/modal-demo.component.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@ import { Subscription } from 'rxjs';
77
selector: 'd-modal-demo',
88
templateUrl: './modal-demo.component.html',
99
styles: [':host ::ng-deep d-button:not(first-child) { margin-left: 8px }'],
10-
})
10+
})
1111
export class ModalDemoComponent implements OnInit, OnDestroy {
1212
basicSource: Array<DevuiSourceData> = [
1313
{ title: 'HTML', language: 'xml', code: require('./basic/basic.component.html?raw') },
1414
{ title: 'TS', language: 'typescript', code: require('./basic/basic.component.ts?raw') },
1515
{ title: 'Dialog HTML', language: 'xml', code: require('./modal-test.component.html?raw') },
1616
{ title: 'Dialog TS', language: 'typescript', code: require('./modal-test.component.ts?raw') },
1717
];
18+
maximizeSource: Array<DevuiSourceData> = [
19+
{ title: 'HTML', language: 'xml', code: require('./maximize/maximize.component.html?raw') },
20+
{ title: 'TS', language: 'typescript', code: require('./maximize/maximize.component.ts?raw') },
21+
{ title: 'Dialog HTML', language: 'xml', code: require('./modal-test.component.html?raw') },
22+
{ title: 'Dialog TS', language: 'typescript', code: require('./modal-test.component.ts?raw') },
23+
];
1824
basicUpdateSource: Array<DevuiSourceData> = [
1925
{ title: 'HTML', language: 'xml', code: require('./basic-update/basic-update.component.html?raw') },
2026
{ title: 'TS', language: 'typescript', code: require('./basic-update/basic-update.component.ts?raw') },
@@ -102,6 +108,7 @@ export class ModalDemoComponent implements OnInit, OnDestroy {
102108
setNavValues(values) {
103109
this.navItems = [
104110
{ dAnchorLink: 'standard-dialog', value: values['standard-dialog'] },
111+
{ dAnchorLink: 'maximize-dialog', value: values['maximize-dialog'] },
105112
{ dAnchorLink: 'custom-dialog', value: values['custom-dialog'] },
106113
{ dAnchorLink: 'intercept-dialog-closed', value: values['intercept-dialog-closed'] },
107114
{ dAnchorLink: 'message-hint', value: values['message-hint'] },

devui/modal/demo/modal-demo.module.ts

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { DDemoNavModule } from 'devui-commons/src/demo-nav/d-demo-nav.module';
1515
import { AutofocusComponent } from './autofocus/autofocus.component';
1616
import { BasicUpdateComponent } from './basic-update/basic-update.component';
1717
import { BasicComponent } from './basic/basic.component';
18+
import { MaximizeComponent } from './maximize/maximize.component';
1819
import { CasesComponent } from './cases/cases.component';
1920
import { ModalCasesComponent } from './cases/modal-cases.component';
2021
import { CustomizeComponent } from './customize/customize.component';
@@ -33,53 +34,54 @@ import { TipsComponent } from './tips/tips.component';
3334

3435
@NgModule({
3536
imports: [
36-
FormsModule,
37-
TranslateModule,
38-
CommonModule,
39-
ModalModule,
40-
ButtonModule,
41-
PopoverModule,
42-
FormModule,
43-
DevUICodeboxModule,
44-
DevUIApiModule,
45-
DDemoNavModule,
46-
TextInputModule,
47-
RouterModule.forChild([
48-
{ path: '', redirectTo: 'demo', pathMatch: 'full' },
49-
{
50-
path: 'design',
51-
component: ModalDesignComponent,
52-
},
53-
{ path: 'demo', component: ModalDemoComponent },
54-
{
55-
path: 'api',
56-
component: DevUIApiComponent,
57-
data: {
58-
'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'),
59-
'en-us': require('!html-loader!markdown-loader!../doc/api-en.md'),
60-
},
61-
},
37+
FormsModule,
38+
TranslateModule,
39+
CommonModule,
40+
ModalModule,
41+
ButtonModule,
42+
PopoverModule,
43+
FormModule,
44+
DevUICodeboxModule,
45+
DevUIApiModule,
46+
DDemoNavModule,
47+
TextInputModule,
48+
RouterModule.forChild([
49+
{ path: '', redirectTo: 'demo', pathMatch: 'full' },
50+
{
51+
path: 'design',
52+
component: ModalDesignComponent,
53+
},
54+
{ path: 'demo', component: ModalDemoComponent },
55+
{
56+
path: 'api',
57+
component: DevUIApiComponent,
58+
data: {
59+
'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'),
60+
'en-us': require('!html-loader!markdown-loader!../doc/api-en.md'),
61+
},
62+
},
6263
]),
6364
],
6465
declarations: [
65-
ModalDemoComponent,
66-
ModalDesignComponent,
67-
ModalTestComponent,
68-
ModalAlertComponent,
69-
ModalNoBtnComponent,
70-
BasicComponent,
71-
CustomizeComponent,
72-
TipsComponent,
73-
HideComponent,
74-
ModalFormComponent,
75-
AutofocusComponent,
76-
TemplateComponent,
77-
DialogContentComponent,
78-
ModalContentComponent,
79-
BasicUpdateComponent,
80-
FixedWrapperComponent,
81-
CasesComponent,
82-
ModalCasesComponent
66+
ModalDemoComponent,
67+
ModalDesignComponent,
68+
ModalTestComponent,
69+
ModalAlertComponent,
70+
ModalNoBtnComponent,
71+
BasicComponent,
72+
MaximizeComponent,
73+
CustomizeComponent,
74+
TipsComponent,
75+
HideComponent,
76+
ModalFormComponent,
77+
AutofocusComponent,
78+
TemplateComponent,
79+
DialogContentComponent,
80+
ModalContentComponent,
81+
BasicUpdateComponent,
82+
FixedWrapperComponent,
83+
CasesComponent,
84+
ModalCasesComponent,
8385
],
84-
})
86+
})
8587
export class ModalDemoModule {}

devui/modal/dialog.service.ts

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { DOCUMENT } from '@angular/common';
2-
import {
3-
ComponentFactoryResolver,
4-
ComponentRef,
5-
Inject,
6-
Injectable,
7-
Renderer2, RendererFactory2
8-
} from '@angular/core';
2+
import { ComponentFactoryResolver, ComponentRef, Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core';
93
import { OverlayContainerRef } from 'ng-devui/overlay-container';
104
import { DevConfigService } from 'ng-devui/utils';
115
import { assign, isUndefined } from 'lodash-es';
@@ -19,10 +13,13 @@ export class DialogService {
1913
private renderer: Renderer2;
2014
document: Document;
2115

22-
constructor(private componentFactoryResolver: ComponentFactoryResolver,
23-
private overlayContainerRef: OverlayContainerRef, private rendererFactory: RendererFactory2,
24-
private devConfigService: DevConfigService,
25-
@Inject(DOCUMENT) private doc: any) {
16+
constructor(
17+
private componentFactoryResolver: ComponentFactoryResolver,
18+
private overlayContainerRef: OverlayContainerRef,
19+
private rendererFactory: RendererFactory2,
20+
private devConfigService: DevConfigService,
21+
@Inject(DOCUMENT) private doc: any
22+
) {
2623
this.renderer = this.rendererFactory.createRenderer(null, null);
2724
this.document = this.doc;
2825
}
@@ -48,6 +45,7 @@ export class DialogService {
4845
componentFactoryResolver,
4946
beforeHidden,
5047
onClose,
48+
onMaximize,
5149
dialogtype = 'standard',
5250
showCloseBtn = true,
5351
draggable = true,
@@ -56,7 +54,8 @@ export class DialogService {
5654
offsetY,
5755
bodyScrollable = true,
5856
contentTemplate,
59-
escapable = true
57+
escapable = true,
58+
showMaximizeBtn = false,
6059
}: IDialogOptions) {
6160
const finalComponentFactoryResolver = componentFactoryResolver || this.componentFactoryResolver;
6261

@@ -95,21 +94,25 @@ export class DialogService {
9594
offsetX,
9695
offsetY,
9796
bodyScrollable,
98-
escapable
97+
escapable,
9998
});
10099

101-
const modalContainerRef = modalRef.instance.modalContainerHost.viewContainerRef
102-
.createComponent(finalComponentFactoryResolver.resolveComponentFactory(ModalContainerComponent), 0, injector);
103-
assign(modalContainerRef.instance, { title, buttons, maxHeight, dialogtype, showCloseBtn });
100+
const modalContainerRef = modalRef.instance.modalContainerHost.viewContainerRef.createComponent(
101+
finalComponentFactoryResolver.resolveComponentFactory(ModalContainerComponent),
102+
0,
103+
injector
104+
);
105+
assign(modalContainerRef.instance, { title, buttons, maxHeight, dialogtype, showCloseBtn, showMaximizeBtn });
104106

105107
if (contentTemplate) {
106108
assign(modalContainerRef.instance, { contentTemplate });
107109
} else {
108110
if (typeof content === 'string') {
109111
assign(modalContainerRef.instance, { content, html });
110112
} else {
111-
this.contentRef = modalContainerRef.instance.modalContentHost.viewContainerRef
112-
.createComponent(finalComponentFactoryResolver.resolveComponentFactory(content));
113+
this.contentRef = modalContainerRef.instance.modalContentHost.viewContainerRef.createComponent(
114+
finalComponentFactoryResolver.resolveComponentFactory(content)
115+
);
113116
assign(this.contentRef.instance, { data, dialogtype });
114117
}
115118
}
@@ -118,7 +121,14 @@ export class DialogService {
118121
modalRef.instance.hide();
119122
};
120123

121-
modalRef.instance.updateButtonOptions = buttonOptions => modalContainerRef.instance.updateButtonOptions(buttonOptions);
124+
modalContainerRef.instance.onMaximize = () => {
125+
modalRef.instance.maximize();
126+
if (onMaximize) {
127+
onMaximize(modalRef.instance.maximized);
128+
}
129+
};
130+
131+
modalRef.instance.updateButtonOptions = (buttonOptions) => modalContainerRef.instance.updateButtonOptions(buttonOptions);
122132

123133
modalRef.instance.onHidden = () => {
124134
if (modalRef.instance.documentOverFlow) {

devui/modal/modal-container.component.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
id="d-modal-header"
44
[title]="title"
55
(closeEvent)="close($event)"
6+
(maximizeEvent)="maximize($event)"
67
[dialogtype]="dialogtype"
8+
[showMaximizeBtn]="showMaximizeBtn"
79
[showCloseBtn]="showCloseBtn"
810
></d-modal-header>
911
<div
1012
class="modal-body devui-scrollbar"
1113
[ngClass]="{
1214
'flex-content': dialogtype === 'warning' || dialogtype === 'failed' || dialogtype === 'success' || dialogtype === 'info'
1315
}"
14-
[ngStyle]="{ maxHeight: maxHeight }"
16+
[ngStyle]="{ maxHeight: maxHeight, 'overflow-y': 'auto' }"
1517
>
1618
<div
1719
[ngClass]="{

devui/modal/modal-container.component.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import {
2-
Component,
3-
Input,
4-
OnInit,
5-
TemplateRef,
6-
ViewChild
7-
} from '@angular/core';
1+
import { Component, Input, OnInit, TemplateRef, ViewChild } from '@angular/core';
82
import { DomSanitizer } from '@angular/platform-browser';
93
import { IButtonStyle } from 'ng-devui/button';
104
import { ModalComponent } from './modal.component';
@@ -14,12 +8,13 @@ import { ModalContentDirective } from './modal.directive';
148
templateUrl: './modal-container.component.html',
159
styleUrls: ['./modal-container.component.scss'],
1610
preserveWhitespaces: false,
17-
})
11+
})
1812
export class ModalContainerComponent implements OnInit {
1913
@Input() maxHeight: string;
2014
@Input() data: any;
2115
@Input() title: string;
2216
@Input() content: string | HTMLElement;
17+
@Input() showMaximizeBtn: boolean;
2318
@Input() buttons: Array<{
2419
id?: string;
2520
cssClass?: IButtonStyle;
@@ -31,10 +26,12 @@ export class ModalContainerComponent implements OnInit {
3126
}>;
3227
@Input() html: boolean;
3328
@Input() onClose: ($event?: Event) => void;
29+
@Input() onMaximize: (maximized: boolean) => void;
3430
@ViewChild(ModalContentDirective, { static: true }) modalContentHost: ModalContentDirective;
3531
@Input() dialogtype = 'standard';
3632
@Input() showCloseBtn: boolean;
3733
contentTemplate: TemplateRef<any>;
34+
_oldMaxHeight: string;
3835

3936
constructor(private sanitizer: DomSanitizer, public modalInstance: ModalComponent) {}
4037

@@ -48,9 +45,21 @@ export class ModalContainerComponent implements OnInit {
4845
this.onClose(event);
4946
}
5047

48+
maximize(maximized: boolean) {
49+
if (this.onMaximize) {
50+
this.onMaximize(maximized);
51+
}
52+
if (maximized) {
53+
this._oldMaxHeight = this.maxHeight;
54+
this.maxHeight = '100vh';
55+
} else {
56+
this.maxHeight = this._oldMaxHeight;
57+
}
58+
}
59+
5160
updateButtonOptions(buttonOptions = []) {
5261
this.buttons = this.buttons.map((button, index) => {
53-
return {...button, ...buttonOptions[index]};
62+
return { ...button, ...buttonOptions[index] };
5463
});
5564
}
5665
}

0 commit comments

Comments
 (0)