diff --git a/components/message/demo/close.md b/components/message/demo/close.md
new file mode 100644
index 00000000000..ac803a52419
--- /dev/null
+++ b/components/message/demo/close.md
@@ -0,0 +1,15 @@
+---
+order: 4
+title:
+ zh-CN: 结束事件
+ en-US: Customize duration
+---
+
+## zh-CN
+
+可通过订阅 `onClose` 事件在 message 关闭时做出某些操作。以上用例将依次打开三个 message。
+
+## en-US
+
+You can subscribe to `onClose` event to make some operations. This case would open three messages in sequence.
+
diff --git a/components/message/demo/close.ts b/components/message/demo/close.ts
new file mode 100644
index 00000000000..c7d4ee02080
--- /dev/null
+++ b/components/message/demo/close.ts
@@ -0,0 +1,24 @@
+import { Component } from '@angular/core';
+import { NzMessageService } from 'ng-zorro-antd';
+import { concatMap } from 'rxjs/operators';
+
+@Component({
+ selector: 'nz-demo-message-close',
+ template: `
+
+ `,
+ styles : []
+})
+export class NzDemoMessageCloseComponent {
+ constructor(private message: NzMessageService) {
+ }
+
+ startShowMessages(): void {
+ this.message.loading('Action in progress', { nzDuration: 2500 }).onClose.pipe(
+ concatMap(() => this.message.success('Loading finished', { nzDuration: 2500 }).onClose),
+ concatMap(() => this.message.info('Loading finished is finished', { nzDuration: 2500 }).onClose)
+ ).subscribe(() => {
+ console.log('All completed!');
+ });
+ }
+}
diff --git a/components/message/doc/index.en-US.md b/components/message/doc/index.en-US.md
index bf553739746..2a6da581a96 100644
--- a/components/message/doc/index.en-US.md
+++ b/components/message/doc/index.en-US.md
@@ -64,3 +64,13 @@ Methods for destruction are also provided:
| nzMaxStack | The maximum number of messages that can be displayed at the same time | `number` | `8` |
| nzPauseOnHover | Do not remove automatically when mouse is over while setting to `true` | `boolean` | `true` |
| nzAnimate | Whether to turn on animation | `boolean` | `true` |
+
+### NzMessageDataFilled
+
+It's the object that returned when you call `NzMessageService.success` and others.
+
+```ts
+export interface NzMessageDataFilled {
+ onClose: Subject; // It would emit an event when the message is closed
+}
+```
diff --git a/components/message/doc/index.zh-CN.md b/components/message/doc/index.zh-CN.md
index 17ed2b1ee98..5818f1e2a80 100644
--- a/components/message/doc/index.zh-CN.md
+++ b/components/message/doc/index.zh-CN.md
@@ -65,3 +65,13 @@ title: Message
| nzMaxStack | 同一时间可展示的最大提示数量 | `number` | `8` |
| nzPauseOnHover | 鼠标移上时禁止自动移除 | `boolean` | `true` |
| nzAnimate | 开关动画效果 | `boolean` | `true` |
+
+### NzMessageDataFilled
+
+当你调用 `NzMessageService.success` 或其他方法时会返回该对象。
+
+```ts
+export interface NzMessageDataFilled {
+ onClose: Subject; // 当 message 关闭时它会派发一个事件
+}
+```
diff --git a/components/message/nz-message-container.component.ts b/components/message/nz-message-container.component.ts
index 80ae97ce240..3aae42846d1 100644
--- a/components/message/nz-message-container.component.ts
+++ b/components/message/nz-message-container.component.ts
@@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Optional, ViewEncapsulation } from '@angular/core';
+import { Subject } from 'rxjs';
import { NzMessageConfig, NZ_MESSAGE_CONFIG, NZ_MESSAGE_DEFAULT_CONFIG } from './nz-message-config';
import { NzMessageDataFilled, NzMessageDataOptions } from './nz-message.definitions';
@@ -26,34 +27,49 @@ export class NzMessageContainerComponent {
this.config = { ...this.config, ...config };
}
- // Create a new message
+ /**
+ * Create a new message.
+ * @param message Parsed message configuration.
+ */
createMessage(message: NzMessageDataFilled): void {
if (this.messages.length >= this.config.nzMaxStack) {
this.messages.splice(0, 1);
}
message.options = this._mergeMessageOptions(message.options);
+ message.onClose = new Subject();
this.messages.push(message);
this.cdr.detectChanges();
}
- // Remove a message by messageId
- removeMessage(messageId: string): void {
+ /**
+ * Remove a message by `messageId`.
+ * @param messageId Id of the message to be removed.
+ * @param userAction Whether this is closed by user interaction.
+ */
+ removeMessage(messageId: string, userAction: boolean = false): void {
this.messages.some((message, index) => {
if (message.messageId === messageId) {
this.messages.splice(index, 1);
this.cdr.detectChanges();
+ message.onClose.next(userAction);
+ message.onClose.complete();
return true;
}
});
}
- // Remove all messages
+ /**
+ * Remove all messages.
+ */
removeMessageAll(): void {
this.messages = [];
this.cdr.detectChanges();
}
- // Merge default options and custom message options
+ /**
+ * Merge default options and custom message options
+ * @param options
+ */
protected _mergeMessageOptions(options: NzMessageDataOptions): NzMessageDataOptions {
const defaultOptions: NzMessageDataOptions = {
nzDuration : this.config.nzDuration,
diff --git a/components/message/nz-message.component.ts b/components/message/nz-message.component.ts
index 2d521dcb8cd..0016a36deb4 100644
--- a/components/message/nz-message.component.ts
+++ b/components/message/nz-message.component.ts
@@ -73,13 +73,13 @@ export class NzMessageComponent implements OnInit, OnDestroy {
}
// Remove self
- protected _destroy(): void {
+ protected _destroy(userAction: boolean = false): void {
if (this._options.nzAnimate) {
this.nzMessage.state = 'leave';
this.cdr.detectChanges();
- setTimeout(() => this._messageContainer.removeMessage(this.nzMessage.messageId), 200);
+ setTimeout(() => this._messageContainer.removeMessage(this.nzMessage.messageId, userAction), 200);
} else {
- this._messageContainer.removeMessage(this.nzMessage.messageId);
+ this._messageContainer.removeMessage(this.nzMessage.messageId, userAction);
}
}
diff --git a/components/message/nz-message.definitions.ts b/components/message/nz-message.definitions.ts
index 1d72ede6348..440baaa1643 100644
--- a/components/message/nz-message.definitions.ts
+++ b/components/message/nz-message.definitions.ts
@@ -1,20 +1,29 @@
+import { Subject } from 'rxjs';
+
+export type NzMessageType = 'success' | 'info' | 'warning' | 'error' | 'loading';
+
export interface NzMessageDataOptions {
nzDuration?: number;
nzAnimate?: boolean;
nzPauseOnHover?: boolean;
}
-// Message data for terminal users
+/**
+ * Message data for terminal users.
+ */
export interface NzMessageData {
- // TODO: remove the literal parts as it's widened anyway
- type?: 'success' | 'info' | 'warning' | 'error' | 'loading' | string;
+ type?: NzMessageType | string;
content?: string;
}
-// Filled version of NzMessageData (includes more private properties)
+/**
+ * Filled version of NzMessageData (includes more private properties).
+ */
export interface NzMessageDataFilled extends NzMessageData {
- messageId: string; // Service-wide unique id, auto generated
- state?: 'enter' | 'leave';
+ messageId: string;
+ createdAt: Date;
+
options?: NzMessageDataOptions;
- createdAt: Date; // Auto created
+ state?: 'enter' | 'leave';
+ onClose?: Subject;
}
diff --git a/components/message/nz-message.service.ts b/components/message/nz-message.service.ts
index b3ecd9acde3..b13fbe8bcaa 100644
--- a/components/message/nz-message.service.ts
+++ b/components/message/nz-message.service.ts
@@ -5,7 +5,7 @@ import { NzMessageConfig } from './nz-message-config';
import { NzMessageContainerComponent } from './nz-message-container.component';
import { NzMessageData, NzMessageDataFilled, NzMessageDataOptions } from './nz-message.definitions';
-let globalCounter = 0; // global ID counter for messages
+let globalCounter = 0;
export class NzMessageBaseService {
protected _container: ContainerClass;
@@ -16,9 +16,8 @@ export class NzMessageBaseService {
tick(1000);
expect(overlayContainerElement.textContent).toContain('EXISTS');
}));
+
+ it('should emit event when message close', fakeAsync(() => {
+ let onCloseFlag = false;
+
+ const msg = messageService.create('loading', 'CLOSE');
+ msg.onClose.subscribe(() => {
+ onCloseFlag = true;
+ });
+
+ demoAppFixture.detectChanges();
+ tick(50000);
+
+ expect(onCloseFlag).toBeTruthy();
+ }));
});
@Component({
diff --git a/components/notification/doc/index.en-US.md b/components/notification/doc/index.en-US.md
index dad9ced2bf3..9638ee1f4b4 100644
--- a/components/notification/doc/index.en-US.md
+++ b/components/notification/doc/index.en-US.md
@@ -79,4 +79,14 @@ Methods for destruction are also provided:
| nzAnimate | Whether to turn on animation | `boolean` | `true` |
| nzTop | The top of the notification when it pops up from the top. | `string` | 24px |
| nzBottom | The bottom of the notification when it pops up from the bottom. | `string` | 24px |
-| nzPlacement | Popup position, optional `topLeft` `topRight` `bottomLeft` `bottomRight` | `string` | `topRight` |
\ No newline at end of file
+| nzPlacement | Popup position, optional `topLeft` `topRight` `bottomLeft` `bottomRight` | `string` | `topRight` |
+
+### NzNotificationDataFilled
+
+It's the object that returned when you call `NzNotificationService.success` and others.
+
+```ts
+export interface NzNotificationDataFilled {
+ onClose: Subject; // It would emit an event when the notification is closed, and emit a `true` if it's closed by user
+}
+```
diff --git a/components/notification/doc/index.zh-CN.md b/components/notification/doc/index.zh-CN.md
index 2e39e4f4b47..a56fbc3d2e0 100644
--- a/components/notification/doc/index.zh-CN.md
+++ b/components/notification/doc/index.zh-CN.md
@@ -79,4 +79,14 @@ subtitle: 通知提醒框
| nzAnimate | 开关动画效果 | `boolean` | `true` |
| nzTop | 消息从顶部弹出时,距离顶部的位置。 | `string` | 24px |
| nzBottom | 消息从底部弹出时,距离底部的位置。 | `string` | 24px |
-| nzPlacement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | `string` | `topRight` |
\ No newline at end of file
+| nzPlacement | 弹出位置,可选 `topLeft` `topRight` `bottomLeft` `bottomRight` | `string` | `topRight` |
+
+### NzNotificationDataFilled
+
+当你调用 `NzNotificationService.success` 或其他方法时会返回该对象。
+
+```ts
+export interface NzNotificationDataFilled {
+ onClose: Subject; // 当 notification 关闭时它会派发一个事件,如果为用户手动关闭会派发 `true`
+}
+```
diff --git a/components/notification/nz-notification-container.component.ts b/components/notification/nz-notification-container.component.ts
index 8c34928e044..19e1a8a6003 100644
--- a/components/notification/nz-notification-container.component.ts
+++ b/components/notification/nz-notification-container.component.ts
@@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Optional, ViewEncapsulation } from '@angular/core';
+import { Subject } from 'rxjs';
import { NzMessageContainerComponent } from '../message/nz-message-container.component';
import { NzNotificationConfig, NZ_NOTIFICATION_CONFIG, NZ_NOTIFICATION_DEFAULT_CONFIG } from './nz-notification-config';
@@ -34,6 +35,7 @@ export class NzNotificationContainerComponent extends NzMessageContainerComponen
*/
createMessage(notification: NzNotificationDataFilled): void {
notification.options = this._mergeMessageOptions(notification.options);
+ notification.onClose = new Subject();
const key = notification.options.nzKey;
const notificationWithSameKey = this.messages.find(msg => msg.options.nzKey === notification.options.nzKey);
if (key && notificationWithSameKey) {
diff --git a/components/notification/nz-notification.component.ts b/components/notification/nz-notification.component.ts
index c088c805149..0d44c89395f 100644
--- a/components/notification/nz-notification.component.ts
+++ b/components/notification/nz-notification.component.ts
@@ -19,7 +19,7 @@ export class NzNotificationComponent extends NzMessageComponent {
}
close(): void {
- this._destroy();
+ this._destroy(true);
}
get state(): string {
diff --git a/components/notification/nz-notification.definitions.ts b/components/notification/nz-notification.definitions.ts
index e45effc5d2c..89a5a949d08 100644
--- a/components/notification/nz-notification.definitions.ts
+++ b/components/notification/nz-notification.definitions.ts
@@ -1,4 +1,5 @@
import { TemplateRef } from '@angular/core';
+import { Subject } from 'rxjs';
import { NzMessageData, NzMessageDataOptions } from '../message/nz-message.definitions';
@@ -21,7 +22,9 @@ export interface NzNotificationDataOptions extends NzMessageDataOptions
// Filled version of NzMessageData (includes more private properties)
export interface NzNotificationDataFilled extends NzNotificationData {
messageId: string; // Service-wide unique id, auto generated
+ createdAt: Date; // Auto created
+
state?: 'enter' | 'leave';
options?: NzNotificationDataOptions;
- createdAt: Date; // Auto created
+ onClose?: Subject;
}
diff --git a/components/notification/nz-notification.spec.ts b/components/notification/nz-notification.spec.ts
index 9119c0163b5..9e567dd6c91 100644
--- a/components/notification/nz-notification.spec.ts
+++ b/components/notification/nz-notification.spec.ts
@@ -175,6 +175,24 @@ describe('NzNotification', () => {
expect(overlayContainerElement.textContent).toContain('SHOULD NOT CHANGE');
expect(overlayContainerElement.querySelector('.ant-notification-notice-icon-success')).not.toBeNull();
});
+
+ it('should receive `true` when it is closed by user', fakeAsync(() => {
+ let onCloseFlag = false;
+
+ messageService.create(null, null, 'close').onClose.subscribe(user => {
+ if (user) {
+ onCloseFlag = true;
+ }
+ });
+
+ demoAppFixture.detectChanges();
+ tick(1000);
+ const closeEl = overlayContainerElement.querySelector('.ant-notification-notice-close');
+ dispatchMouseEvent(closeEl, 'click');
+ tick(1000);
+ expect(onCloseFlag).toBeTruthy();
+ tick(50000);
+ }));
});
@Component({