Skip to content

Commit

Permalink
feat(module:tabs): support link router (NG-ZORRO#3718)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wendell authored Jul 18, 2019
1 parent 997c1f9 commit f6e9653
Show file tree
Hide file tree
Showing 17 changed files with 278 additions and 16 deletions.
3 changes: 2 additions & 1 deletion components/descriptions/nz-descriptions.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<div *ngIf="nzTitle" class="ant-descriptions-title">
<div *ngIf="nzTitle"
class="ant-descriptions-title">
<ng-container *nzStringTemplateOutlet="nzTitle">{{ nzTitle }}</ng-container>
</div>
<div class="ant-descriptions-view">
Expand Down
14 changes: 14 additions & 0 deletions components/tabs/demo/link-router.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
order: 13
title:
zh-CN: 路由联动
en-US: With Router
---

## zh-CN

与路由联动,点击 tab 更改路由,并且在路由改变时自动切换 tab。

## en-US

Link with router.
26 changes: 26 additions & 0 deletions components/tabs/demo/link-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-tabs-link-router',
template: `
<nz-tabset nzLinkRouter>
<nz-tab>
<a nz-tab-link [routerLink]="['.']" [queryParams]="{ tab: 'one' }" queryParamsHandling="merge">Default</a>
Default.
</nz-tab>
<nz-tab>
<a nz-tab-link [routerLink]="['.']" [queryParams]="{ tab: 'two' }" queryParamsHandling="merge">Two</a>
Two.
</nz-tab>
<nz-tab>
<a nz-tab-link [routerLink]="['.']" [queryParams]="{ tab: 'three' }" queryParamsHandling="merge">Three</a>
Three.
</nz-tab>
<nz-tab>
<a nz-tab-link [routerLink]="['.']" [queryParams]="{ tab: 'four' }" queryParamsHandling="merge">Four</a>
Four.
</nz-tab>
</nz-tabset>
`
})
export class NzDemoTabsLinkRouterComponent {}
11 changes: 10 additions & 1 deletion components/tabs/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
| `[nzTabBarGutter]` | The gap between tabs | `number` | - |
| `[nzHideAll]` | Whether hide all tabs | `boolean` | `false` |
| `[nzShowPagination]` | Whether show pre or next button when exceed display area | `boolean` | `true` |
| `[nzLinkRouter]` | Link with Angular router. It supports child mode and query param mode | `boolean` | `false` ||
| `(nzSelectedIndexChange)` | Current tab's index change callback | `EventEmitter<number>` | - |
| `(nzSelectChange)` | Current tab's change callback | `EventEmitter<{nzSelectedIndex: number,tab: NzTabComponent}>` | - |
| `(nzOnNextClick)` | Callback executed when next button is clicked | `EventEmitter<void>` | - |
Expand All @@ -57,4 +58,12 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';

### [nz-tab]

Tab contents can be lazy loaded by declaring the body in a `ng-template` with the `[nz-tab]` attribute.
Tab contents can be lazy loaded by declaring the body in a `ng-template` with the `[nz-tab]` attribute.

### nz-tab-link

Show a link in tab's head. Used in router link mode.

### Link Router

This make the tabs component changes `nzSelectedIndex` with Angular route. You must use `nz-tab-link` instead of `[nzTitle]` in this situation.
12 changes: 10 additions & 2 deletions components/tabs/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
| `[nzTabBarGutter]` | tabs 之间的间隙 | `number` | - |
| `[nzHideAll]` | 是否隐藏所有tab内容 | `boolean` | `false` |
| `[nzShowPagination]` | 是否超出范围时显示pre和next按钮 | `boolean` | `true` |
| `[nzLinkRouter]` | 与 Angular 路由联动 | `boolean` | `false` ||
| `(nzSelectedIndexChange)` | 当前激活 tab 面板的 序列号变更回调函数 | `EventEmitter<number>` | - |
| `(nzSelectChange)` | 当前激活 tab 面板变更回调函数 | `EventEmitter<{nzSelectedIndex: number,tab: NzTabComponent}>` | - |
| `(nzOnNextClick)` | next 按钮被点击的回调 | `EventEmitter<void>` | - |
Expand All @@ -58,7 +59,14 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
| `(nzSelect)` | tab被选中的回调函数 | `EventEmitter<void>` | - |
| `(nzDeselect)` | tab被取消选中的回调函数 | `EventEmitter<void>` | - |


### [nz-tab]

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

### [nz-tab-link]

选项卡头显示链接,在路由联动模式下使用。

### 路由联动

路由联动可以让 tab 的切换和路由行为相一致。使用此功能时,title 必须通过 `nz-tab-link` 组件指定。
24 changes: 24 additions & 0 deletions components/tabs/nz-tab-link.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @license
* Copyright Alibaba.com All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { Directive, Optional, Self } from '@angular/core';
import { RouterLink, RouterLinkWithHref } from '@angular/router';

/**
* This component is for catching `routerLink` directive.
*/
@Directive({
selector: 'a[nz-tab-link]',
exportAs: 'nzTabLink'
})
export class NzTabLinkDirective {
constructor(
@Optional() @Self() public routerLink?: RouterLink,
@Optional() @Self() public routerLinkWithHref?: RouterLinkWithHref
) {}
}
5 changes: 4 additions & 1 deletion components/tabs/nz-tab.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<ng-template>
<ng-template #titleTpl>
<ng-content select="[nz-tab-link]"></ng-content>
</ng-template>
<ng-template #bodyTpl>
<ng-content></ng-content>
</ng-template>
7 changes: 6 additions & 1 deletion components/tabs/nz-tab.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
import { Subject } from 'rxjs';

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

import { NzTabLinkDirective } from './nz-tab-link.directive';
import { NzTabDirective } from './nz-tab.directive';

@Component({
Expand All @@ -40,9 +42,12 @@ export class NzTabComponent implements OnChanges, OnDestroy {
origin: number | null = null;
isActive = false;
readonly stateChanges = new Subject<void>();
@ViewChild(TemplateRef, { static: true }) content: TemplateRef<void>;
@ViewChild('bodyTpl', { static: true }) content: TemplateRef<void>;
@ViewChild('titleTpl', { static: true }) title: TemplateRef<void>;
@ContentChild(NzTabDirective, { static: false, read: TemplateRef }) template: TemplateRef<void>;
@ContentChild(NzTabLinkDirective, { static: false }) linkDirective: NzTabLinkDirective;
@Input() nzTitle: string | TemplateRef<void>;
@Input() nzRouterIdentifier: string;
@Input() @InputBoolean() nzForceRender = false;
@Input() @InputBoolean() nzDisabled = false;
@Output() readonly nzClick = new EventEmitter<void>();
Expand Down
7 changes: 5 additions & 2 deletions components/tabs/nz-tabs.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { NzIconModule } from 'ng-zorro-antd/icon';

import { NzTabBodyComponent } from './nz-tab-body.component';
import { NzTabLabelDirective } from './nz-tab-label.directive';
import { NzTabLinkDirective } from './nz-tab-link.directive';
import { NzTabComponent } from './nz-tab.component';
import { NzTabDirective } from './nz-tab.directive';
import { NzTabsInkBarDirective } from './nz-tabs-ink-bar.directive';
Expand All @@ -28,7 +29,8 @@ import { NzTabSetComponent } from './nz-tabset.component';
NzTabsNavComponent,
NzTabLabelDirective,
NzTabsInkBarDirective,
NzTabBodyComponent
NzTabBodyComponent,
NzTabLinkDirective
],
exports: [
NzTabComponent,
Expand All @@ -37,7 +39,8 @@ import { NzTabSetComponent } from './nz-tabset.component';
NzTabsNavComponent,
NzTabLabelDirective,
NzTabsInkBarDirective,
NzTabBodyComponent
NzTabBodyComponent,
NzTabLinkDirective
],
imports: [CommonModule, ObserversModule, NzIconModule, NzAddOnModule]
})
Expand Down
101 changes: 100 additions & 1 deletion components/tabs/nz-tabs.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { CommonModule } from '@angular/common';
import { Component, DebugElement, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { fakeAsync, tick, ComponentFixture, TestBed } from '@angular/core/testing';
import { fakeAsync, flush, tick, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Router, Routes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';

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

import { NzTabsModule } from './nz-tabs.module';
Expand Down Expand Up @@ -481,6 +485,67 @@ describe('tabs', () => {
});
});

describe('link router', () => {
let fixture: ComponentFixture<NzTestTabsLinkRouterComponent>;
let tabs: DebugElement;
let router: Router;

describe('basic', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [CommonModule, NzTabsModule, RouterTestingModule.withRoutes(routes)],
declarations: [NzTestTabsLinkRouterComponent]
}).compileComponents();

fixture = TestBed.createComponent(NzTestTabsLinkRouterComponent);
fixture.detectChanges();

tabs = fixture.debugElement.query(By.directive(NzTabSetComponent));
});

it('should child route mode works', fakeAsync(() => {
fixture.ngZone!.run(() => {
router = TestBed.get(Router);
router.initialNavigation();

fixture.detectChanges();
expect((tabs.componentInstance as NzTabSetComponent).nzSelectedIndex).toBe(0);

router.navigate(['.', 'two']);
fixture.detectChanges();
tick(200);
fixture.detectChanges();
expect((tabs.componentInstance as NzTabSetComponent).nzSelectedIndex).toBe(1);

flush();
// const titles = tabs.nativeElement.querySelectorAll('.ant-tabs-tab');
// titles[0].click();
// fixture.detectChanges();
// tick(200);
// fixture.detectChanges();
// expect(location.path()).toBe('/');
});
}));
});

describe('throw error', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NzTabsModule],
declarations: [NzTestTabsLinkRouterComponent]
});
});

it('should raise error when routerModule is not imported', () => {
expect(() => {
TestBed.compileComponents();
fixture = TestBed.createComponent(NzTestTabsLinkRouterComponent);
fixture.detectChanges();
}).toThrowError();
});
});
});

@Component({
encapsulation: ViewEncapsulation.None,
styleUrls: ['../style/index.less', './style/index.less'],
Expand Down Expand Up @@ -575,3 +640,37 @@ export class NzTestTabsBasicComponent {
export class NzTestTabsTabPositionLeftComponent {
tabs = [1, 2, 3];
}

@Component({
template: `
<nz-tabset nzLinkRouter>
<nz-tab nzTitle="default">
<a nz-tab-link [routerLink]="['.']">One</a>
One
</nz-tab>
<nz-tab nzTitle="two">
<a nz-tab-link [routerLink]="['.', 'two']">Two</a>
Two
</nz-tab>
</nz-tabset>
<router-outlet></router-outlet>
`
})
export class NzTestTabsLinkRouterComponent {}

const routes: Routes = [
{
path: '',
component: NzTestTabsLinkRouterComponent,
data: {
path: ''
}
},
{
path: 'two',
component: NzTestTabsLinkRouterComponent,
data: {
path: 'two'
}
}
];
2 changes: 1 addition & 1 deletion components/tabs/nz-tabset.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
[disabled]="tab.nzDisabled"
(click)="clickLabel(i,tab.nzDisabled)"
*ngFor="let tab of listOfNzTabComponent; let i = index">
<ng-container *nzStringTemplateOutlet="tab.nzTitle">{{ tab.nzTitle }}</ng-container>
<ng-container *nzStringTemplateOutlet="tab.nzTitle || tab.title">{{ tab.nzTitle }}</ng-container>
</div>
</div>
<div #tabContent
Expand Down
Loading

0 comments on commit f6e9653

Please sign in to comment.