Skip to content

Commit 347745a

Browse files
authoredAug 14, 2022
feat(abc:reuse-tab): add canClose property (#1497)
1 parent f108d97 commit 347745a

File tree

5 files changed

+24
-5
lines changed

5 files changed

+24
-5
lines changed
 

‎packages/abc/reuse-tab/index.en-US.md

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ Turning on `keepingScroll` will restore the previous scrollbar position after re
225225
| `[disabled]` | Whether to disabled | `boolean` | `false` |
226226
| `[titleRender]` | Custom rendering of the title | `TemplateRef<{ $implicit: ReuseItem }>` | - |
227227
| `[storageState]` | Whether to store the state, keep the last browser state | `boolean` | `false` |
228+
| `[canClose]` | A function to determine what should be closed | `(options: { item: ReuseItem; includeNonCloseable: boolean }) => Observable<boolean>` | - |
228229
| `(close)` | Close callback event | `EventEmitter` | - |
229230
| `(change)` | Callback when switching | `EventEmitter` | - |
230231

‎packages/abc/reuse-tab/index.zh-CN.md

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ alainProvides.push({
4242
> **注意:若不指定 `(activate)` 事件,无法刷新未缓存过的当前标签页。**
4343
4444
> 位置 `src/app/layout/layout.module.ts`
45+
4546
```ts
4647
import { ReuseTabModule } from '@delon/abc/reuse-tab'; // 新增 import
4748

@@ -227,6 +228,7 @@ export class DemoComponent implements OnReuseInit, OnReuseDestroy {
227228
| `[disabled]` | 是否禁用 | `boolean` | `false` |
228229
| `[titleRender]` | 自定义标题渲染 | `TemplateRef<{ $implicit: ReuseItem }>` | - |
229230
| `[storageState]` | 是否存储状态,保持最后一次浏览器的状态 | `boolean` | `false` |
231+
| `[canClose]` | 关闭时二次校验 | `(options: { item: ReuseItem; includeNonCloseable: boolean }) => Observable<boolean>` | - |
230232
| `(close)` | 关闭回调 | `EventEmitter` | - |
231233
| `(change)` | 切换时回调,接收的参数至少包含:`active``list` 两个参数 | `EventEmitter` | - |
232234

‎packages/abc/reuse-tab/reuse-tab.component.spec.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick
33
import { By } from '@angular/platform-browser';
44
import { ExtraOptions, Router, RouteReuseStrategy, ROUTER_CONFIGURATION } from '@angular/router';
55
import { RouterTestingModule } from '@angular/router/testing';
6-
import { Observable } from 'rxjs';
6+
import { Observable, of } from 'rxjs';
77

88
import { ALAIN_I18N_TOKEN, DelonLocaleModule, DelonLocaleService, en_US, MenuService, zh_CN } from '@delon/theme';
99
import { ScrollService } from '@delon/util/browser';
@@ -12,6 +12,7 @@ import { NzSafeAny } from 'ng-zorro-antd/core/types';
1212
import { AlainI18NServiceFake } from '../../theme/src/services/i18n/i18n';
1313
import { ReuseTabComponent } from './reuse-tab.component';
1414
import {
15+
ReuseCanClose,
1516
ReuseCustomContextMenu,
1617
ReuseItem,
1718
ReuseTabMatchMode,
@@ -167,6 +168,12 @@ describe('abc: reuse-tab', () => {
167168
it('issues-363', fakeAsync(() => {
168169
page.to('#b').expectCount(2).close(1).expectCount(1).expectAttr(0, 'closable', false).end();
169170
}));
171+
it('#canClose', fakeAsync(() => {
172+
layoutComp.canClose = () => of(false);
173+
page.cd().to('#b').expectCount(2).close(1).expectCount(2);
174+
layoutComp.canClose = () => of(true);
175+
page.cd().to('#b').expectCount(2).close(1).expectCount(1).end();
176+
}));
170177
});
171178

172179
describe('#title', () => {
@@ -858,6 +865,7 @@ class AppComponent {}
858865
[disabled]="disabled"
859866
[titleRender]="titleRender"
860867
[storageState]="storageState"
868+
[canClose]="canClose"
861869
(change)="change($event)"
862870
(close)="close($event)"
863871
>
@@ -884,6 +892,7 @@ class LayoutComponent {
884892
disabled = false;
885893
titleRender?: TemplateRef<{ $implicit: ReuseItem }>;
886894
storageState = false;
895+
canClose?: ReuseCanClose;
887896
change(): void {}
888897
close(): void {}
889898
}

‎packages/abc/reuse-tab/reuse-tab.component.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
ViewEncapsulation
2121
} from '@angular/core';
2222
import { ActivatedRoute, Router } from '@angular/router';
23-
import { Subject, debounceTime, filter, takeUntil } from 'rxjs';
23+
import { Subject, debounceTime, filter, takeUntil, of } from 'rxjs';
2424

2525
import { AlainI18NService, ALAIN_I18N_TOKEN } from '@delon/theme';
2626
import { BooleanInput, InputBoolean, InputNumber, NumberInput } from '@delon/util/decorator';
@@ -29,6 +29,7 @@ import { NzTabSetComponent } from 'ng-zorro-antd/tabs';
2929

3030
import { ReuseTabContextService } from './reuse-tab-context.service';
3131
import {
32+
ReuseCanClose,
3233
ReuseContextCloseEvent,
3334
ReuseContextI18n,
3435
ReuseCustomContextMenu,
@@ -98,6 +99,7 @@ export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy {
9899
@Input() routeParamMatchMode: ReuseTabRouteParamMatchMode = 'strict';
99100
@Input() @InputBoolean() disabled = false;
100101
@Input() titleRender?: TemplateRef<{ $implicit: ReuseItem }>;
102+
@Input() canClose?: ReuseCanClose;
101103
@Output() readonly change = new EventEmitter<ReuseItem>();
102104
@Output() readonly close = new EventEmitter<ReuseItem | null>();
103105

@@ -251,9 +253,11 @@ export class ReuseTabComponent implements OnInit, OnChanges, OnDestroy {
251253
e.stopPropagation();
252254
}
253255
const item = this.list[idx];
254-
this.srv.close(item.url, includeNonCloseable);
255-
this.close.emit(item);
256-
this.cdr.detectChanges();
256+
(this.canClose ? this.canClose({ item, includeNonCloseable }) : of(true)).pipe(filter(v => v)).subscribe(() => {
257+
this.srv.close(item.url, includeNonCloseable);
258+
this.close.emit(item);
259+
this.cdr.detectChanges();
260+
});
257261
return false;
258262
}
259263

‎packages/abc/reuse-tab/reuse-tab.interfaces.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ActivatedRouteSnapshot } from '@angular/router';
2+
import { Observable } from 'rxjs';
23

34
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
45

@@ -136,3 +137,5 @@ export interface ReuseComponentInstance {
136137
_onReuseDestroy: () => void;
137138
destroy: () => void;
138139
}
140+
141+
export type ReuseCanClose = (options: { item: ReuseItem; includeNonCloseable: boolean }) => Observable<boolean>;

0 commit comments

Comments
 (0)
Please sign in to comment.