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): add nzCanDeactivate hook #4476

Merged
merged 8 commits into from
Jan 8, 2020
Merged
Show file tree
Hide file tree
Changes from 2 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
23 changes: 23 additions & 0 deletions components/core/util/observable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @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 { from, isObservable, of, Observable } from 'rxjs';
import { isPromise } from './is-promise';

export function wrapIntoObservable<T>(value: T | Promise<T> | Observable<T>): Observable<T> {
if (isObservable(value)) {
return value;
}

if (isPromise(value)) {
// Use `Promise.resolve()` to wrap promise-like instances.
return from(Promise.resolve(value));
}

return of(value);
}
1 change: 1 addition & 0 deletions components/core/util/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ export * from './text-measure';
export * from './measure-scrollbar';
export * from './ensure-in-bounds';
export * from './tick';
export * from './observable';
14 changes: 14 additions & 0 deletions components/tabs/demo/guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
order: 14
title:
zh-CN: 切换钩子
en-US: Switch hooks
---

## zh-CN

通过钩子函数去判断一个 tab 是否可以被切换。

## en-US

Via hooks to determine if a tab can be switch.
51 changes: 51 additions & 0 deletions components/tabs/demo/guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NzModalService } from 'ng-zorro-antd/modal';
import { Observable } from 'rxjs';

@Component({
selector: 'nz-demo-tabs-guard',
template: `
<nz-tabset [nzCanChange]="canChange">
<nz-tab nzTitle="Tab 1">
Content of Tab Pane 1
</nz-tab>
<nz-tab nzTitle="Tab 2">
Content of Tab Pane 2
</nz-tab>
<nz-tab nzTitle="Tab 3" [nzCanDeactivate]="canDeactivate">
Content of Tab Pane 3
</nz-tab>
</nz-tabset>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NzDemoTabsGuardComponent {
constructor(private modal: NzModalService) {}

canChange = (fromIndex: number, toIndex: number) => {
console.log(fromIndex, toIndex);
if (toIndex === 0) {
return true;
}

return this.confirm();
};

canDeactivate = () => this.confirm();

private confirm(): Observable<boolean> {
return new Observable(observer => {
this.modal.confirm({
nzTitle: '确定离开当前标签?',
nzOnOk: () => {
observer.next(true);
observer.complete();
},
nzOnCancel: () => {
observer.next(false);
observer.complete();
}
});
});
}
}
3 changes: 2 additions & 1 deletion components/tabs/demo/module
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzSelectModule } from 'ng-zorro-antd/select';
import { NzRadioModule } from 'ng-zorro-antd/radio';
import { NzInputNumberModule } from 'ng-zorro-antd/input-number';
import { NzModalModule } from 'ng-zorro-antd/modal';

export const moduleList = [ NzTabsModule, NzIconModule, NzSelectModule, NzRadioModule, NzInputNumberModule, NzButtonModule ];
export const moduleList = [ NzTabsModule, NzIconModule, NzSelectModule, NzRadioModule, NzInputNumberModule, NzButtonModule, NzModalModule ];
5 changes: 4 additions & 1 deletion components/tabs/nz-tab.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { Subject } from 'rxjs';
import { Observable, Subject } from 'rxjs';

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

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

export type NzCanDeactivateFn = () => Observable<boolean> | Promise<boolean> | boolean;

@Component({
selector: 'nz-tab',
exportAs: 'nzTab',
Expand All @@ -50,6 +52,7 @@ export class NzTabComponent implements OnChanges, OnDestroy {
@Input() nzRouterIdentifier: string;
@Input() @InputBoolean() nzForceRender = false;
@Input() @InputBoolean() nzDisabled = false;
@Input() nzCanDeactivate: NzCanDeactivateFn | null = null;
@Output() readonly nzClick = new EventEmitter<void>();
@Output() readonly nzSelect = new EventEmitter<void>();
@Output() readonly nzDeselect = new EventEmitter<void>();
Expand Down
36 changes: 32 additions & 4 deletions components/tabs/nz-tabset.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ import {
ViewEncapsulation
} from '@angular/core';
import { NavigationEnd, Router, RouterLink, RouterLinkWithHref } from '@angular/router';
import { merge, Subject, Subscription } from 'rxjs';
import { merge, Observable, Subject, Subscription } from 'rxjs';

import {
toNumber,
wrapIntoObservable,
InputBoolean,
NzConfigService,
NzFourDirectionType,
Expand All @@ -44,7 +45,7 @@ import {
PREFIX,
WithConfig
} from 'ng-zorro-antd/core';
import { filter, startWith, takeUntil } from 'rxjs/operators';
import { filter, first, startWith, takeUntil } from 'rxjs/operators';

import { NzTabComponent } from './nz-tab.component';
import { NzTabsNavComponent } from './nz-tabs-nav.component';
Expand All @@ -59,6 +60,8 @@ export class NzTabChangeEvent {
tab: NzTabComponent;
}

export type NzCanChangeFn = (fromIndex: number, toIndex: number) => Observable<boolean> | Promise<boolean> | boolean;

export type NzTabPosition = NzFourDirectionType;
export type NzTabPositionMode = 'horizontal' | 'vertical';
export type NzTabType = 'line' | 'card';
Expand Down Expand Up @@ -110,6 +113,7 @@ export class NzTabSetComponent

@Input() @InputBoolean() nzLinkRouter = false;
@Input() @InputBoolean() nzLinkExact = true;
@Input() nzCanChange: NzCanChangeFn | null = null;

@Output() readonly nzOnNextClick = new EventEmitter<void>();
@Output() readonly nzOnPrevClick = new EventEmitter<void>();
Expand Down Expand Up @@ -167,11 +171,35 @@ export class NzTabSetComponent
clickLabel(index: number, disabled: boolean): void {
if (!disabled) {
const tabs = this.listOfNzTabComponent.toArray();
this.nzSelectedIndex = index;
tabs[index].nzClick.emit();
if (this.nzSelectedIndex !== null && this.nzSelectedIndex !== index) {
this.changeHandler(index, tabs);
} else {
this.emitClickEvent(index, tabs);
}
}
}

private changeHandler(index: number, tabs: NzTabComponent[]): void {
const currSelectedTab = tabs[this.nzSelectedIndex!];
let observable: Observable<boolean> | null = null;
if (typeof currSelectedTab.nzCanDeactivate === 'function') {
observable = wrapIntoObservable(currSelectedTab.nzCanDeactivate());
} else if (typeof this.nzCanChange === 'function') {
danranVm marked this conversation as resolved.
Show resolved Hide resolved
observable = wrapIntoObservable(this.nzCanChange(this.nzSelectedIndex!, index));
}
if (observable) {
observable.pipe(first()).subscribe(canChange => canChange && this.emitClickEvent(index, tabs));
danranVm marked this conversation as resolved.
Show resolved Hide resolved
} else {
this.emitClickEvent(index, tabs);
}
}

private emitClickEvent(index: number, tabs: NzTabComponent[]): void {
this.nzSelectedIndex = index;
tabs[index].nzClick.emit();
this.cdr.markForCheck();
}

createChangeEvent(index: number): NzTabChangeEvent {
const event = new NzTabChangeEvent();
event.index = index;
Expand Down
2 changes: 1 addition & 1 deletion docs/recommendation.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ title: 资源推荐
工具库|[Component Dev Kit](https://material.angular.io/cdk/categories) | Angular 官方的提供的组件库工具,包含拖拽、浮层、虚拟滚动等大量功能
可视化|[NGX-CHARTS](https://swimlane.github.io/ngx-charts/) | 基于 D3 的Angular 可视化组件库
可视化|[NGX-CHARTS-DAG](https://swimlane.github.io/ngx-graph/) | 基于 Dagre 的有向无环图可视化组件库
无线端|[NG-ZORRO-MOBILE](http://ng.mobile.ant.design/) | Ant Design Mobile 设计规范的 Angular 实现
无线端|[NG-ZORRO-MOBILE](https://ng.mobile.ant.design/) | Ant Design Mobile 设计规范的 Angular 实现
打包 |[Angular CLI](https://cli.angular.io/) | Angular 的配套打包工具
服务端渲染|[Angular Universal](https://universal.angular.io/) | Angular服务端渲染工具

Expand Down
2 changes: 1 addition & 1 deletion scripts/site/_site/doc/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
<div class="footer-center">
<h2>{{ language === 'zh' ? '相关资源' : 'Resources' }}</h2>
<div>
<a href="http://ng.mobile.ant.design" target="_blank" rel="noopener noreferrer">NG-ZORRO-MOBILE</a>
<a href="https://ng.mobile.ant.design" target="_blank" rel="noopener noreferrer">NG-ZORRO-MOBILE</a>
<span> - </span>
<span>Angular</span>
</div>
Expand Down