Skip to content

Commit

Permalink
feat(module:message): support template (#3102)
Browse files Browse the repository at this point in the history
* feat(module:message): support template

* docs: update content type

* fix: createMessage

* fix: lint

* fix: test

close #3081
  • Loading branch information
Wendell authored and hsuanxyz committed Mar 20, 2019
1 parent b57fb06 commit d3f6655
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 38 deletions.
2 changes: 1 addition & 1 deletion components/message/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ This components provides some service methods, with usage and arguments as follo

| Argument | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| content | The content of message | `string` | - |
| content | The content of message | `string|TemplateRef<void>` | - |
| options | Support setting the parameters for the current message box, see the table below | `object` | - |

The parameters that are set by the `options` support are as follows:
Expand Down
2 changes: 1 addition & 1 deletion components/message/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ title: Message

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| content | 提示内容 | `string` | - |
| content | 提示内容 | `string|TemplateRef<void>` | - |
| options | 支持设置针对当前提示框的参数,见下方表格 | `object` | - |

`options` 支持设置的参数如下:
Expand Down
6 changes: 4 additions & 2 deletions components/message/nz-message.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
<i *ngSwitchCase="'error'" nz-icon type="close-circle"></i>
<i *ngSwitchCase="'loading'" nz-icon type="loading"></i>
</ng-container>
<span [innerHTML]="nzMessage.content"></span>
<ng-container *nzStringTemplateOutlet="nzMessage.content">
<span [innerHTML]="nzMessage.content"></span>
</ng-container>
</div>
</div>
</div>
</div>
3 changes: 2 additions & 1 deletion components/message/nz-message.definitions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TemplateRef } from '@angular/core';
import { Subject } from 'rxjs';

export type NzMessageType = 'success' | 'info' | 'warning' | 'error' | 'loading';
Expand All @@ -13,7 +14,7 @@ export interface NzMessageDataOptions {
*/
export interface NzMessageData {
type?: NzMessageType | string;
content?: string;
content?: string | TemplateRef<void>;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion components/message/nz-message.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { OverlayModule } from '@angular/cdk/overlay';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { NzAddOnModule } from '../core/addon/addon.module';
import { NzIconModule } from '../icon/nz-icon.module';

import { NZ_MESSAGE_DEFAULT_CONFIG_PROVIDER } from './nz-message-config';
Expand All @@ -9,7 +10,7 @@ import { NzMessageComponent } from './nz-message.component';
import { NzMessageService } from './nz-message.service';

@NgModule({
imports : [ CommonModule, OverlayModule, NzIconModule ],
imports : [ CommonModule, OverlayModule, NzIconModule, NzAddOnModule ],
declarations : [ NzMessageContainerComponent, NzMessageComponent ],
providers : [ NZ_MESSAGE_DEFAULT_CONFIG_PROVIDER, NzMessageService ],
entryComponents: [ NzMessageContainerComponent ]
Expand Down
30 changes: 19 additions & 11 deletions components/message/nz-message.service.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { Overlay } from '@angular/cdk/overlay';
import { ApplicationRef, ComponentFactoryResolver, EmbeddedViewRef, Injectable, Injector, Type } from '@angular/core';
import { ApplicationRef, ComponentFactoryResolver, EmbeddedViewRef, Injectable, Injector, TemplateRef, Type } from '@angular/core';

import { NzMessageConfig } from './nz-message-config';
import { NzMessageContainerComponent } from './nz-message-container.component';
import { NzMessageData, NzMessageDataFilled, NzMessageDataOptions } from './nz-message.definitions';

let globalCounter = 0;

export class NzMessageBaseService<ContainerClass extends NzMessageContainerComponent, MessageData, MessageConfig extends NzMessageConfig> {
export class NzMessageBaseService<
ContainerClass extends NzMessageContainerComponent,
MessageData,
MessageConfig extends NzMessageConfig
> {
protected _container: ContainerClass;

constructor(
Expand All @@ -31,11 +35,11 @@ export class NzMessageBaseService<ContainerClass extends NzMessageContainerCompo

createMessage(message: MessageData, options?: NzMessageDataOptions): NzMessageDataFilled {
const resultMessage: NzMessageDataFilled = {
...(message as {}),
...(message as NzMessageData),
...{
createdAt: new Date(),
messageId: this._generateMessageId(),
options,
createdAt: new Date()
options
}
};
this._container.createMessage(resultMessage);
Expand Down Expand Up @@ -81,27 +85,31 @@ export class NzMessageService extends NzMessageBaseService<NzMessageContainerCom
}

// Shortcut methods
success(content: string, options?: NzMessageDataOptions): NzMessageDataFilled {
success(content: string | TemplateRef<void>, options?: NzMessageDataOptions): NzMessageDataFilled {
return this.createMessage({ type: 'success', content }, options);
}

error(content: string, options?: NzMessageDataOptions): NzMessageDataFilled {
error(content: string | TemplateRef<void>, options?: NzMessageDataOptions): NzMessageDataFilled {
return this.createMessage({ type: 'error', content }, options);
}

info(content: string, options?: NzMessageDataOptions): NzMessageDataFilled {
info(content: string | TemplateRef<void>, options?: NzMessageDataOptions): NzMessageDataFilled {
return this.createMessage({ type: 'info', content }, options);
}

warning(content: string, options?: NzMessageDataOptions): NzMessageDataFilled {
warning(content: string | TemplateRef<void>, options?: NzMessageDataOptions): NzMessageDataFilled {
return this.createMessage({ type: 'warning', content }, options);
}

loading(content: string, options?: NzMessageDataOptions): NzMessageDataFilled {
loading(content: string | TemplateRef<void>, options?: NzMessageDataOptions): NzMessageDataFilled {
return this.createMessage({ type: 'loading', content }, options);
}

create(type: 'success' | 'info' | 'warning' | 'error' | 'loading' | string, content: string, options?: NzMessageDataOptions): NzMessageDataFilled {
create(
type: 'success' | 'info' | 'warning' | 'error' | 'loading' | string,
content: string | TemplateRef<void>,
options?: NzMessageDataOptions
): NzMessageDataFilled {
return this.createMessage({ type, content }, options);
}
}
59 changes: 38 additions & 21 deletions components/message/nz-message.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import { OverlayContainer } from '@angular/cdk/overlay';
import { Component } from '@angular/core';
import { Component, TemplateRef, ViewChild } from '@angular/core';
import { fakeAsync, inject, tick, ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';

Expand All @@ -14,7 +14,8 @@ describe('NzMessage', () => {
let messageService: NzMessageService;
let overlayContainer: OverlayContainer;
let overlayContainerElement: HTMLElement;
let demoAppFixture: ComponentFixture<NzTestMessageBasicComponent>;
let fixture: ComponentFixture<NzTestMessageBasicComponent>;
let testComponent: NzTestMessageBasicComponent;

beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
Expand All @@ -37,12 +38,13 @@ describe('NzMessage', () => {
});

beforeEach(() => {
demoAppFixture = TestBed.createComponent(NzTestMessageBasicComponent);
fixture = TestBed.createComponent(NzTestMessageBasicComponent);
testComponent = fixture.debugElement.componentInstance;
});

it('should open a message box with success', (() => {
messageService.success('SUCCESS');
demoAppFixture.detectChanges();
fixture.detectChanges();

expect((overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement).style.zIndex).toBe('1010');
expect(overlayContainerElement.textContent).toContain('SUCCESS');
Expand All @@ -51,39 +53,47 @@ describe('NzMessage', () => {

it('should open a message box with error', (() => {
messageService.error('ERROR');
demoAppFixture.detectChanges();
fixture.detectChanges();

expect(overlayContainerElement.textContent).toContain('ERROR');
expect(overlayContainerElement.querySelector('.anticon-close-circle')).not.toBeNull();
}));

it('should open a message box with warning', (() => {
messageService.warning('WARNING');
demoAppFixture.detectChanges();
fixture.detectChanges();

expect(overlayContainerElement.textContent).toContain('WARNING');
expect(overlayContainerElement.querySelector('.anticon-exclamation-circle')).not.toBeNull();
}));

it('should open a message box with info', (() => {
messageService.info('INFO');
demoAppFixture.detectChanges();
fixture.detectChanges();

expect(overlayContainerElement.textContent).toContain('INFO');
expect(overlayContainerElement.querySelector('.anticon-info-circle')).not.toBeNull();
}));

it('should open a message box with loading', (() => {
messageService.loading('LOADING');
demoAppFixture.detectChanges();
fixture.detectChanges();

expect(overlayContainerElement.textContent).toContain('LOADING');
expect(overlayContainerElement.querySelector('.anticon-loading')).not.toBeNull();
}));

it('should support template', fakeAsync(() => {
messageService.info(testComponent.template);
fixture.detectChanges();

expect(overlayContainerElement.textContent).toContain('Content in template');
tick(10000);
}));

it('should auto closed by 1s', fakeAsync(() => {
messageService.create('', 'EXISTS', { nzDuration: 1000 });
demoAppFixture.detectChanges();
fixture.detectChanges();

expect(overlayContainerElement.textContent).toContain('EXISTS');

Expand All @@ -93,7 +103,7 @@ describe('NzMessage', () => {

it('should not destroy when hovered', fakeAsync(() => {
messageService.create('', 'EXISTS', { nzDuration: 3000 });
demoAppFixture.detectChanges();
fixture.detectChanges();

const messageElement = overlayContainerElement.querySelector('.ant-message-notice')!;
dispatchMouseEvent(messageElement, 'mouseenter');
Expand All @@ -107,23 +117,23 @@ describe('NzMessage', () => {

it('should not destroyed automatically but manually', fakeAsync(() => {
const filledMessage = messageService.success('SUCCESS', { nzDuration: 0 });
demoAppFixture.detectChanges();
fixture.detectChanges();

tick(50000);
expect(overlayContainerElement.textContent).toContain('SUCCESS');

messageService.remove(filledMessage.messageId);
demoAppFixture.detectChanges();
fixture.detectChanges();
expect(overlayContainerElement.textContent).not.toContain('SUCCESS');
}));

it('should keep the balance of messages length and then remove all', fakeAsync(() => {
[ 1, 2, 3 ].forEach(id => {
const content = `SUCCESS-${id}`;
messageService.success(content);
demoAppFixture.detectChanges();
fixture.detectChanges();
tick();
demoAppFixture.detectChanges();
fixture.detectChanges();

expect(overlayContainerElement.textContent).toContain(content);
if (id === 3) {
Expand All @@ -133,22 +143,22 @@ describe('NzMessage', () => {
});

messageService.remove();
demoAppFixture.detectChanges();
fixture.detectChanges();
expect(overlayContainerElement.textContent).not.toContain('SUCCESS-3');
expect((messageService as any)._container.messages.length).toBe(0); // tslint:disable-line:no-any
}));

it('should destroy without animation', fakeAsync(() => {
messageService.error('EXISTS', { nzDuration: 1000, nzAnimate: false });
demoAppFixture.detectChanges();
fixture.detectChanges();
tick(1000 + 10);
expect(overlayContainerElement.textContent).not.toContain('EXISTS');
}));

it('should reset default config dynamically', fakeAsync(() => {
messageService.config({ nzDuration: 0 });
messageService.create('loading', 'EXISTS');
demoAppFixture.detectChanges();
fixture.detectChanges();
tick(1000);
expect(overlayContainerElement.textContent).toContain('EXISTS');
}));
Expand All @@ -159,14 +169,15 @@ describe('NzMessage', () => {
msg.onClose!.subscribe(() => {
onCloseFlag = true;
});
demoAppFixture.detectChanges();

fixture.detectChanges();
tick(50000);
expect(onCloseFlag).toBeTruthy();
}));

it('should container top to configured', fakeAsync(() => {
messageService.create('top', 'CHANGE');
demoAppFixture.detectChanges();
fixture.detectChanges();

const messageContainerElement = overlayContainerElement.querySelector('.ant-message') as HTMLElement;
expect(messageContainerElement.style.top).toBe('24px');
Expand All @@ -177,6 +188,12 @@ describe('NzMessage', () => {

@Component({
selector: 'nz-demo-app-component',
template: ``
template: `
<ng-template #contentTemplate>
Content in template
</ng-template>
`
})
export class NzTestMessageBasicComponent {}
export class NzTestMessageBasicComponent {
@ViewChild('contentTemplate') template: TemplateRef<void>;
}

0 comments on commit d3f6655

Please sign in to comment.