Skip to content

Commit 8e121dd

Browse files
authored
fix: backport tab-view (#5)
1 parent a25ebf8 commit 8e121dd

File tree

4 files changed

+141
-1
lines changed

4 files changed

+141
-1
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { AfterViewInit, Directive, ElementRef, Input, OnInit, TemplateRef, ViewContainerRef } from '@angular/core';
2+
import { TabView, TabViewItem } from '@nativescript/core';
3+
4+
import { InvisibleNode } from '../../views';
5+
import { NativeScriptDebug } from '../../trace';
6+
import { isBlank } from '../../utils';
7+
8+
type TextTransform = 'initial' | 'none' | 'capitalize' | 'uppercase' | 'lowercase';
9+
export interface TabViewItemDef {
10+
title?: string;
11+
iconSource?: string;
12+
textTransform?: TextTransform;
13+
}
14+
15+
@Directive({
16+
selector: 'TabView', // eslint-disable-line @angular-eslint/directive-selector
17+
})
18+
export class TabViewDirective implements AfterViewInit {
19+
public tabView: TabView;
20+
private _selectedIndex: number;
21+
private viewInitialized: boolean;
22+
23+
@Input()
24+
get selectedIndex(): number {
25+
return this._selectedIndex;
26+
}
27+
28+
set selectedIndex(value) {
29+
this._selectedIndex = value;
30+
if (this.viewInitialized) {
31+
this.tabView.selectedIndex = this._selectedIndex;
32+
}
33+
}
34+
35+
constructor(element: ElementRef) {
36+
this.tabView = element.nativeElement;
37+
}
38+
39+
ngAfterViewInit() {
40+
this.viewInitialized = true;
41+
if (NativeScriptDebug.isLogEnabled()) {
42+
NativeScriptDebug.rendererLog('this._selectedIndex: ' + this._selectedIndex);
43+
}
44+
if (!isBlank(this._selectedIndex)) {
45+
this.tabView.selectedIndex = this._selectedIndex;
46+
}
47+
}
48+
}
49+
50+
@Directive({
51+
selector: '[tabItem]', // eslint-disable-line @angular-eslint/directive-selector
52+
})
53+
export class TabViewItemDirective implements OnInit {
54+
private item: TabViewItem;
55+
private _config: TabViewItemDef;
56+
57+
constructor(private owner: TabViewDirective, private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) {}
58+
59+
@Input('tabItem')
60+
set config(config: TabViewItemDef) {
61+
if (!this._config || this._config.iconSource !== config.iconSource || this._config.title !== config.title || this._config.textTransform !== config.textTransform) {
62+
this._config = config;
63+
this.applyConfig();
64+
}
65+
}
66+
67+
get config(): TabViewItemDef {
68+
// tslint:disable-line:no-input-rename
69+
return this._config || {};
70+
}
71+
72+
@Input()
73+
set title(title: string) {
74+
this.config = Object.assign(this.config, { title });
75+
}
76+
77+
get title() {
78+
return this.config.title;
79+
}
80+
81+
@Input()
82+
set iconSource(iconSource: string) {
83+
this.config = Object.assign(this.config, { iconSource });
84+
}
85+
86+
get iconSource() {
87+
return this.config.iconSource;
88+
}
89+
90+
@Input()
91+
set textTransform(textTransform: TextTransform) {
92+
this.config = Object.assign(this.config, { textTransform });
93+
}
94+
95+
get textTransform() {
96+
return this.config.textTransform;
97+
}
98+
99+
private ensureItem() {
100+
if (!this.item) {
101+
this.item = new TabViewItem();
102+
}
103+
}
104+
105+
private applyConfig() {
106+
this.ensureItem();
107+
108+
if (this.config.title) {
109+
this.item.title = this.config.title;
110+
}
111+
112+
if (this.config.iconSource) {
113+
this.item.iconSource = this.config.iconSource;
114+
}
115+
116+
// TabViewItem textTransform has a default value for Android that kick in
117+
// only if no value (even a null value) is set.
118+
if (this.config.textTransform) {
119+
this.item.textTransform = this.config.textTransform;
120+
}
121+
}
122+
123+
ngOnInit() {
124+
this.applyConfig();
125+
126+
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
127+
// Filter out text nodes and comments
128+
const realViews = viewRef.rootNodes.filter((node) => !(node instanceof InvisibleNode));
129+
130+
if (realViews.length > 0) {
131+
this.item.view = realViews[0];
132+
133+
const newItems = (this.owner.tabView.items || []).concat([this.item]);
134+
this.owner.tabView.items = newItems;
135+
}
136+
}
137+
}

packages/angular/src/lib/element-registry/common-views.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,6 @@ export function registerNativeScriptViewComponents() {
4444
registerElement('WrapLayout', () => WrapLayout);
4545
registerElement('FormattedString', () => FormattedString);
4646
registerElement('Span', () => Span);
47+
registerElement('TabView', () => TabView);
4748
}
4849
}

packages/angular/src/lib/nativescript-common.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { ActionBarComponent, ActionBarScope, ActionItemDirective, NavigationButt
55
import { ListViewComponent, TemplateKeyDirective } from './cdk/list-view/list-view.component';
66
import { registerNativeScriptViewComponents } from './element-registry';
77
import { ModalDialogService } from './legacy/directives/dialogs';
8+
import { TabViewDirective, TabViewItemDirective } from './cdk/tab-view';
89

9-
const CDK_COMPONENTS = [ActionBarComponent, ActionBarScope, ActionItemDirective, NavigationButtonDirective, ListViewComponent, TemplateKeyDirective];
10+
const CDK_COMPONENTS = [ActionBarComponent, ActionBarScope, ActionItemDirective, NavigationButtonDirective, ListViewComponent, TemplateKeyDirective, TabViewDirective, TabViewItemDirective];
1011

1112
registerNativeScriptViewComponents();
1213

packages/angular/src/lib/public_api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export * from './rootcomposite.module';
1212
export * from './cdk/list-view';
1313
export * from './cdk/portal';
1414
export * from './cdk/dialog';
15+
export * from './cdk/tab-view';
1516
export * from './file-system';
1617
export * from './nativescript-common.module';
1718
export * from './loading.service';

0 commit comments

Comments
 (0)