Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(module:tabs): support (nzContextmenu) event #5749

Merged
merged 1 commit into from
Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/tabs/demo/slide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { NzTabPosition } from 'ng-zorro-antd/tabs';
[nzDisabled]="tab.disabled"
(nzSelect)="log(['select', tab])"
(nzClick)="log(['click', tab])"
(nzContextmenu)="log(['contextmenu', tab])"
(nzDeselect)="log(['deselect', tab])"
>
{{ tab.content }}
Expand Down
47 changes: 34 additions & 13 deletions components/tabs/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
| `(nzSelectedIndexChange)` | Current tab's index change callback | `EventEmitter<number>` | - |
| `(nzSelectChange)` | Current tab's change callback | `EventEmitter<{index: number,tab: NzTabComponent}>` | - |

### nz-tabset[nzType="editable-card"]

| Property | Description | Type | Default | Global Config |
| --- | --- | --- | --- | --- |
| `[nzHideAdd]` | Hide plus icon or not | `boolean` | `false` |
| `[nzAddIcon]` | Add icon | `string \| TemplateRef<void>` | - |
| `(nzAdd)` | When add button clicked emit | `EventEmitter<>` | - |
| `(nzClose)` | When close button clicked emit | `EventEmitter<{ index: number }>` | - |

### nz-tab

| Property | Description | Type | Default |
Expand All @@ -50,25 +59,41 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
| `[nzForceRender]` | Forced render of content in tabs, not lazy render after clicking on tabs | `boolean` | `false` |
| `[nzDisabled]` | tab disable | `boolean` | - |
| `(nzClick)` | title click callback | `EventEmitter<void>` | - |
| `(nzContextmenu)` | title contextmenu callback | `EventEmitter<MouseEvent>` | - |
| `(nzSelect)` | title select callback | `EventEmitter<void>` | - |
| `(nzDeselect)` | title deselect callback | `EventEmitter<void>` | - |

### nz-tabset[nzType="editable-card"]

| Property | Description | Type | Default | Global Config |
| --- | --- | --- | --- | --- |
| `[nzHideAdd]` | Hide plus icon or not | `boolean` | `false` |
| `[nzAddIcon]` | Add icon | `string \| TemplateRef<void>` | - |
| `(nzAdd)` | When add button clicked emit | `EventEmitter<>` | - |
| `(nzClose)` | When close button clicked emit | `EventEmitter<{ index: number }>` | - |

### nz-tabset[nzType="editable-card"] > nz-tab
| Property | Description | Type | Default | Global Config |
| --- | --- | --- | --- | --- |
| `[nzClosable]` | Show close icon or not | `boolean` | `false` |
| `[nzCloseIcon]` | Close icon | `string \| TemplateRef<void>` | - |


#### Template variable references of `nz-tab[nzTitle]`

| Property | Description | Type |
| --- | --- | --- |
| `visible` | Is the title in the visible area, will be rendered to the dropdown menu if `false`. | `boolean`|

Use in `nz-tab[nzTitle]`

```html
<nz-tab [nzTitle]="titleTemplate">
...
<ng-template #titleTemplate let-visible="visible">...</ng-template>
</nz-tab>
```

Use in `*nzTabLink`

```html
<nz-tab>
<a *nzTabLink="let visible = visible" nz-tab-link [routerLink]="['.']">...</a>
</nz-tab>
```


### [nz-tab]

Tab contents can be lazy loaded by declaring the body in a `ng-template` with the `[nz-tab]` attribute.
Expand All @@ -85,7 +110,3 @@ Show a link in tab's head. Used in router link mode.
</nz-tab>
</nz-tabset>
```

### Link Router

This make the tabs component changes `nzSelectedIndex` with Angular route. You must use `nz-tab-link` instead of `[nzTitle]` in this situation.
52 changes: 36 additions & 16 deletions components/tabs/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,6 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
| `(nzSelectedIndexChange)` | 当前激活 tab 面板的 序列号变更回调函数 | `EventEmitter<number>` | - |
| `(nzSelectChange)` | 当前激活 tab 面板变更回调函数 | `EventEmitter<{index: number,tab: NzTabComponent}>` | - |

### nz-tab

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `[nzTitle]` | 选项卡头显示文字 | `string \| TemplateRef<void>` | - |
| `[nzForceRender]` | 被隐藏时是否渲染 DOM 结构 | `boolean` | `false` |
| `[nzDisabled]` | 是否禁用 | `boolean` | - |
| `(nzClick)` | title被点击的回调函数 | `EventEmitter<void>` | - |
| `(nzSelect)` | tab被选中的回调函数 | `EventEmitter<void>` | - |
| `(nzDeselect)` | tab被取消选中的回调函数 | `EventEmitter<void>` | - |

### nz-tabset[nzType="editable-card"]

| 参数 | 说明 | 类型 | 默认值 | 全局配置 |
Expand All @@ -65,19 +54,54 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
| `(nzAdd)` | 点击添加按钮时的事件 | `EventEmitter<>` | - |
| `(nzClose)` | 点击删除按钮时的事件 | `EventEmitter<{ index: number }>` | - |


### nz-tab

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `[nzTitle]` | 选项卡头显示文字 | `string \| TemplateRef<TabTemplateContext>` | - |
| `[nzForceRender]` | 被隐藏时是否渲染 DOM 结构 | `boolean` | `false` |
| `[nzDisabled]` | 是否禁用 | `boolean` | - |
| `(nzClick)` | 单击 title 的回调函数 | `EventEmitter<void>` | - |
| `(nzContextmenu)` | 右键 title 的回调函数 | `EventEmitter<MouseEvent>` | - |
| `(nzSelect)` | tab 被选中的回调函数 | `EventEmitter<void>` | - |
| `(nzDeselect)` | tab 被取消选中的回调函数 | `EventEmitter<void>` | - |

### nz-tabset[nzType="editable-card"] > nz-tab
| 参数 | 说明 | 类型 | 默认值 | 全局配置 |
| --- | --- | --- | --- | --- |
| `[nzClosable]` | 显示删除按钮 | `boolean` | `false` |
| `[nzCloseIcon]` | 关闭按钮图标 | `string \| TemplateRef<void>` | - |


#### `nz-tab[nzTitle]` 的模版引用变量

| 属性 | 说明 | 类型 |
| --- | --- | --- |
| `visible` | 表示是否在可见区域, 为 `false` 时将会被渲染到下拉菜单中 | `boolean` |

在 `nz-tab[nzTitle]` 中使用
```html
<nz-tab [nzTitle]="titleTemplate">
...
<ng-template #titleTemplate let-visible="visible">...</ng-template>
</nz-tab>
```

在 `*nzTabLink` 中使用
```html
<nz-tab>
<a *nzTabLink="let visible = visible" nz-tab-link [routerLink]="['.']">...</a>
</nz-tab>
```

### [nz-tab]

与 `ng-template` 一同使用,用于标记需要懒加载的 `tab` 内容,具体用法见示例。

### ng-template[nzTabLink] > a[nz-tab-link]

选项卡头显示链接,在路由联动模式下使用
路由联动可以让 tab 的切换和路由行为相一致

```html
<nz-tabset nzLinkRouter>
Expand All @@ -87,7 +111,3 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
</nz-tab>
</nz-tabset>
```

### 路由联动

路由联动可以让 tab 的切换和路由行为相一致。使用此功能时,title 必须通过 `nz-tab-link` 组件指定。
4 changes: 4 additions & 0 deletions components/tabs/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ interface NzTabTouchScrollEvent {

export type NzTabScrollEvent = NzTabTouchScrollEvent | NzTabWheelScrollEvent;
export type NzTabScrollEventHandlerFun<T extends NzTabScrollEvent['event']> = (event: T) => void;

export interface TabTemplateContext {
visible: boolean;
}
4 changes: 3 additions & 1 deletion components/tabs/tab-link.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { RouterLink, RouterLinkWithHref } from '@angular/router';

import { warnDeprecation } from 'ng-zorro-antd/core/logger';

import { TabTemplateContext } from './interfaces';

/**
* Fix https://github.com/angular/angular/issues/8563
*/
Expand All @@ -16,7 +18,7 @@ import { warnDeprecation } from 'ng-zorro-antd/core/logger';
exportAs: 'nzTabLinkTemplate'
})
export class NzTabLinkTemplateDirective {
constructor(@Host() public templateRef: TemplateRef<void>) {}
constructor(@Host() public templateRef: TemplateRef<TabTemplateContext>) {}
}

/**
Expand Down
8 changes: 7 additions & 1 deletion components/tabs/tab-nav-operation.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ import { NzTabNavItemDirective } from './tab-nav-item.directive';
[nzSelected]="item.active"
[nzDisabled]="item.disabled"
(click)="onSelect(item)"
(contextmenu)="onContextmenu(item, $event)"
>
<ng-container *nzStringTemplateOutlet="item.tab.label">{{ item.tab.label }}</ng-container>
<ng-container *nzStringTemplateOutlet="item.tab.label; context: { visible: false }">{{ item.tab.label }}</ng-container>
</li>
</ul>
</nz-dropdown-menu>
Expand Down Expand Up @@ -88,6 +89,11 @@ export class NzTabNavOperationComponent implements OnDestroy {
}
}

onContextmenu(item: NzTabNavItemDirective, e: MouseEvent): void {
if (!item.disabled) {
item.tab.nzContextmenu.emit(e);
}
}
showItems(): void {
clearTimeout(this.closeAnimationWaitTimeoutId);
this.menuOpened = true;
Expand Down
6 changes: 4 additions & 2 deletions components/tabs/tab.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { TabTemplateContext } from './interfaces';

import { Subject } from 'rxjs';

Expand Down Expand Up @@ -52,14 +53,15 @@ export class NzTabComponent implements OnChanges, OnDestroy, OnInit {
static ngAcceptInputType_nzClosable: BooleanInput;
static ngAcceptInputType_nzForceRender: BooleanInput;

@Input() nzTitle: string | TemplateRef<void> = '';
@Input() nzTitle: string | TemplateRef<TabTemplateContext> = '';
@Input() @InputBoolean() nzClosable = false;
@Input() nzCloseIcon: string | TemplateRef<NzSafeAny> = 'close';
@Input() @InputBoolean() nzDisabled = false;
@Input() @InputBoolean() nzForceRender = false;
@Output() readonly nzSelect = new EventEmitter<void>();
@Output() readonly nzDeselect = new EventEmitter<void>();
@Output() readonly nzClick = new EventEmitter<void>();
@Output() readonly nzContextmenu = new EventEmitter<MouseEvent>();

/**
* @deprecated Will be removed in 11.0.0
Expand All @@ -80,7 +82,7 @@ export class NzTabComponent implements OnChanges, OnDestroy, OnInit {
return this.template || this.contentTemplate;
}

get label(): string | TemplateRef<void> {
get label(): string | TemplateRef<NzSafeAny> {
return this.nzTitle || this.nzTabLinkTemplateDirective?.templateRef || this.tabLinkTemplate;
}

Expand Down
68 changes: 41 additions & 27 deletions components/tabs/tabset.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { ENTER, LEFT_ARROW, RIGHT_ARROW, SPACE } from '@angular/cdk/keycodes';
import { OverlayContainer } from '@angular/cdk/overlay';
import { CommonModule } from '@angular/common';
import { Component, DebugElement, OnInit, QueryList, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { Router, Routes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { dispatchKeyboardEvent } from 'ng-zorro-antd/core/testing';
import { dispatchFakeEvent, dispatchKeyboardEvent } from 'ng-zorro-antd/core/testing';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzIconTestModule } from 'ng-zorro-antd/icon/testing';
import { NzTabNavBarComponent } from 'ng-zorro-antd/tabs/tab-nav-bar.component';
Expand Down Expand Up @@ -599,11 +600,15 @@ describe('NzTabSet', () => {
describe('scrollable', () => {
let fixture: ComponentFixture<ScrollableTabsTestComponent>;
let element: HTMLElement;

let overlayContainerElement: HTMLElement;
beforeEach(fakeAsync(() => {
fixture = TestBed.createComponent(ScrollableTabsTestComponent);
element = fixture.nativeElement;

inject([OverlayContainer], (oc: OverlayContainer) => {
overlayContainerElement = oc.getContainerElement();
})();

fixture.detectChanges();
tick(300);
fixture.detectChanges();
Expand All @@ -615,6 +620,26 @@ describe('NzTabSet', () => {
expect(element.querySelector('nz-tab-nav-operation')).not.toBeNull();
});

it('should get the correct outlet', fakeAsync(() => {
fixture.detectChanges();
flush(300);
fixture.detectChanges();
const inTabs = fixture.debugElement.queryAll(By.css('.ant-tabs-tab'));
inTabs.forEach(tab => {
expect(tab.nativeElement.textContent.trim()).toBe('Title in tabs');
});

dispatchFakeEvent(element.querySelector('nz-tab-nav-operation')!, 'mouseenter');
fixture.detectChanges();
flush(300);
fixture.detectChanges();

const inMenu = overlayContainerElement.querySelectorAll<HTMLLIElement>('.ant-tabs-dropdown-menu-item');
inMenu.forEach((tab: HTMLLIElement) => {
expect(tab.textContent!.trim()).toBe('Title in menu');
});
}));

it('should set transform to visible when selected invisible tab', fakeAsync(() => {
const tabsList = element.querySelector('.ant-tabs-nav-list')! as HTMLElement;
const translateX = getTranslate(tabsList.style.transform).x;
Expand Down Expand Up @@ -803,15 +828,9 @@ xdescribe('NzTabSet router', () => {
[nzCentered]="centered"
[nzCanDeactivate]="canDeactivate"
>
<nz-tab nzTitle="Tab 0" nzClosable>
Content of Tab Pane 0
</nz-tab>
<nz-tab nzTitle="Tab 1" nzClosable>
Content of Tab Pane 1
</nz-tab>
<nz-tab nzTitle="Tab 2">
Content of Tab Pane 2
</nz-tab>
<nz-tab nzTitle="Tab 0" nzClosable>Content of Tab Pane 0</nz-tab>
<nz-tab nzTitle="Tab 1" nzClosable>Content of Tab Pane 1</nz-tab>
<nz-tab nzTitle="Tab 2">Content of Tab Pane 2</nz-tab>
</nz-tabset>
`
})
Expand Down Expand Up @@ -841,9 +860,7 @@ class SimpleTabsTestComponent {
@Component({
template: `
<nz-tabset nzType="editable-card" [(nzSelectedIndex)]="selectedIndex" [nzAddIcon]="addTemplate">
<nz-tab nzTitle="Tab 0">
Content of Tab Pane 0
</nz-tab>
<nz-tab nzTitle="Tab 0">Content of Tab Pane 0</nz-tab>
<nz-tab nzClosable [nzTitle]="titleTemplate" [nzCloseIcon]="closeIconTemplate">
<ng-template nz-tab>
<span class="content">Template Content of Tab Pane 1</span>
Expand All @@ -869,15 +886,9 @@ class TemplateTabsTestComponent {
@Component({
template: `
<nz-tabset nzType="editable-card" [(nzSelectedIndex)]="selectedIndex" (nzSelectedIndexChange)="handleSelection($event)">
<nz-tab nzTitle="Tab 0">
Content of Tab Pane 0
</nz-tab>
<nz-tab nzTitle="Tab 1" nzClosable [nzDisabled]="disabled">
Content of Tab Pane 1
</nz-tab>
<nz-tab nzTitle="Tab 2" nzDisabled>
Content of Tab Pane 2
</nz-tab>
<nz-tab nzTitle="Tab 0">Content of Tab Pane 0</nz-tab>
<nz-tab nzTitle="Tab 1" nzClosable [nzDisabled]="disabled">Content of Tab Pane 1</nz-tab>
<nz-tab nzTitle="Tab 2" nzDisabled>Content of Tab Pane 2</nz-tab>
</nz-tabset>
`
})
Expand Down Expand Up @@ -922,7 +933,10 @@ class DynamicTabsTestComponent {
(nzSelectedIndexChange)="handleSelection($event)"
[nzTabPosition]="position"
>
<nz-tab *ngFor="let _tab of tabs; let i = index" [nzTitle]="'Tab ' + i">Content of Tab Pane {{ i }}</nz-tab>
<nz-tab *ngFor="let _tab of tabs; let i = index" [nzTitle]="titleTemplate">
<ng-template #titleTemplate let-visible="visible">Title in {{ visible ? 'tabs' : 'menu' }}</ng-template>
Content of Tab Pane {{ i }}
</nz-tab>
</nz-tabset>
</div>
`,
Expand Down Expand Up @@ -1014,11 +1028,11 @@ class DeprecatedAPITabsTestComponent {
template: `
<nz-tabset nzLinkRouter>
<nz-tab nzTitle="default">
<a nz-tab-link [routerLink]="['.']">One</a>
<a *nzTabLink nz-tab-link [routerLink]="['.']">One</a>
One
</nz-tab>
<nz-tab nzTitle="two">
<a nz-tab-link [routerLink]="['.', 'two']">Two</a>
<a *nzTabLink nz-tab-link [routerLink]="['.', 'two']">Two</a>
Two
</nz-tab>
</nz-tabset>
Expand Down
Loading