8000 feat: add support for Tabs and BottomNavigation (#524) · drewjbartlett/nativescript-vue@806658b · GitHub
[go: up one dir, main page]

Skip to content

Commit 806658b

Browse files
MartoYankovrigor789
authored andcommitted
feat: add support for Tabs and BottomNavigation (nativescript-vue#524)
* feat: add support for Tabs and BottomNavigation * refactor: fix tab navigation samples
1 parent a86ab2b commit 806658b

File tree

10 files changed

+269
-5
lines changed

10 files changed

+269
-5
lines changed

platform/nativescript/element-registry.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,57 @@ registerElement(
148148
}
149149
)
150150

151+
registerElement(
152+
'BottomNavigation',
153+
() => require('tns-core-modules/ui/bottom-navigation').BottomNavigation,
154+
{
155+
model: {
156+
prop: 'selectedIndex',
157+
event: 'selectedIndexChange'
158+
},
159+
component: builtInComponents.BottomNavigation
160+
}
161+
)
162+
163+
registerElement(
164+
'Tabs',
165+
() => require('tns-core-modules/ui/tabs').Tabs,
166+
{
167+
model: {
168+
prop: 'selectedIndex',
169+
event: 'selectedIndexChange'
170+
},
171+
component: builtInComponents.Tabs
172+
}
173+
)
174+
175+
registerElement(
176+
'TabStrip',
177+
() => require('tns-core-modules/ui/tab-navigation-base/tab-strip').TabStrip,
178+
{
179+
skipAddToDom: true,
180+
component: builtInComponents.TabStrip
181+
}
182+
)
183+
184+
registerElement(
185+
'TabStripItem',
186+
() => require('tns-core-modules/ui/tab-navigation-base/tab-strip-item').TabStripItem,
187+
{
188+
skipAddToDom: true,
189+
component: builtInComponents.TabStripItem
190+
}
191+
)
192+
193+
registerElement(
194+
'TabContentItem',
195+
() => require('tns-core-modules/ui/tab-navigation-base/tab-content-item').TabContentItem,
196+
{
197+
skipAddToDom: true,
198+
component: builtInComponents.TabContentItem
199+
}
200+
)
201+
151202
registerElement('transition', null, {
152203
component: builtInComponents.transition
153204
})
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export default {
2+
model: {
3+
prop: 'selectedIndex',
4+
event: 'selectedIndexChange'
5+
},
6+
7+
render(h) {
8+
return h(
9+
'NativeBottomNavigation',
10+
{
11+
on: this.$listeners,
12+
attrs: this.$attrs
13+
},
14+
this.$slots.default
15+
)
16+
},
17+
18+
methods: {
19+
registerTabStrip(tabStrip) {
20+
this.$el.setAttribute('tabStrip', tabStrip)
21+
},
22+
registerTabContentItem(tabContentItem) {
23+
const items = this.$el.nativeView.items || []
24+
25+
this.$el.setAttribute('items', items.concat([tabContentItem]))
26+
}
27+
}
28+
}

platform/nativescript/runtime/components/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@ export { default as ListView } from './list-view'
66
export { default as Page } from './page'
77
export { default as TabView } from './tab-view'
88
export { default as TabViewItem } from './tab-view-item'
9+
export { default as BottomNavigation } from './bottom-navigation'
10+
export { default as Tabs } from './tabs'
11+
export { default as TabStrip } from './tab-strip'
12+
export { default as TabStripItem } from './tab-strip-item'
13+
export { default as TabContentItem } from './tab-content-item'
914
export { default as transition } from './transition'
1015
export { default as VTemplate } from './v-template'
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { warn } from 'core/util/debug'
2+
3+
export default {
4+
template: `<NativeTabContentItem><slot /></NativeTabContentItem>`,
5+
6+
mounted() {
7+
if (this.$el.childNodes.length > 1) {
8+
warn('TabContentItem should contain only 1 root element', this)
9+
}
10+
11+
let _nativeView = this.$el.nativeView
12+
_nativeView.view = this.$el.childNodes[0].nativeView
13+
this.$parent.registerTabContentItem(_nativeView)
14+
}
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default {
2+
template: `<NativeTabStripItem><slot /></NativeTabStripItem>`,
3+
4+
mounted() {
5+
let _nativeView = this.$el.nativeView
6+
this.$parent.registerTabStripItem(_nativeView)
7+
}
8+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export default {
2+
render(h) {
3+
return h(
4+
'NativeTabStrip',
5+
{
6+
on: this.$listeners,
7+
attrs: this.$attrs
8+
},
9+
this.$slots.default
10+
)
11+
},
12+
13+
mounted() {
14+
let _nativeView = this.$el.nativeView
15+
this.$parent.registerTabStrip(_nativeView)
16+
},
17+
18+
methods: {
19+
registerTabStripItem(tabStripItem) {
20+
const items = this.$el.nativeView.items || []
21+
22+
this.$el.setAttribute('items', items.concat([tabStripItem]))
23+
}
24+
}
25+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export default {
2+
model: {
3+
prop: 'selectedIndex',
4+
event: 'selectedIndexChange'
5+
},
6+
7+
render(h) {
8+
return h(
9+
'NativeTabs',
10+
{
11+
on: this.$listeners,
12+
attrs: this.$attrs
13+
},
14+
this.$slots.default
15+
)
16+
},
17+
18+
methods: {
19+
registerTabStrip(tabStrip) {
20+
this.$el.setAttribute('tabStrip', tabStrip)
21+
},
22+
registerTabContentItem(tabContentItem) {
23+
const items = this.$el.nativeView.items || []
24+
25+
this.$el.setAttribute('items', items.concat([tabContentItem]))
26+
}
27+
}
28+
}
Lines changed: 51 additions & 0 deletions
+
</ActionBar>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const Vue = require('nativescript-vue')
2+
3+
Vue.config.debug = true
4+
5+
let app = new Vue({
6+
data: {
7+
activeTab: 1,
8+
tabs: [
9+
{ title: 'First Tab', text: 'im the first tab' },
10+
{ title: 'Second Tab', text: 'im the second tab' },
11+
{ title: 'Third Tab', text: 'im the third tab' }
12+
]
13+
},
14+
15+
template: `
16+
<Frame>
17+
<Page>
18+
<ActionBar title="test">
19+
<StackLayout orientation="horizontal" horizontalAlignment="center">
20+
<Image src="res://icon" style="width: 30; height: 30; vertical-align: center; margin-right: 10;" />
21+
<Label style="font-size: 20; vertical-align: center;">
22+
<FormattedString>
23+
<Span text="Bottom" fontWeight="Bold" />
24+
<Span text="Navigation" />
25+
</FormattedString>
26+
</Label>
27+
</StackLayout>
28
29+
<StackLayout>
30+
<Label :text="activeTab" />
31+
<Button text="Click me!" @tap="tabs.push({title: 'added', text: 'added tab'})" />
32+
<button text="Go to last!" @tap="activeTab = tabs.length - 1" />
33+
34+
<GridLayout>
35+
<BottomNavigation v-model="activeTab">
36+
<TabStrip>
37+
<TabStripItem v-for="(tab, i) in tabs" :key="i + tab.title" :title="tab.title"></TabStripItem>
38+
</TabStrip>
39+
40+
<TabContentItem v-for="(tab, i) in tabs" :key="i + tab.title">
41+
<Label text="tab.text" />
42+
</TabContentItem>
43+
</BottomNavigation>
44+
</GridLayout>
45+
</StackLayout>
46+
</Page>
47+
</Frame>
48+
`
49+
})
50+
51+
app.$start()

samples/app/app-with-tab-view.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ let app = new Vue({
3131
<Button text="Click me!" @tap="tabs.push({title: 'added', text: 'added tab'})" />
3232
<button text="Go to last!" @tap="activeTab = tabs.length - 1" />
3333
34-
<TabView v-model="activeTab">
35-
<TabViewItem v-for="(tab, i) in tabs" :key="i + tab.title" :title="tab.title">
36-
<Label text="tab.text" />
37-
</TabViewItem>
38-
</TabView>
34+
<GridLayout>
35+
<TabView v-model="activeTab">
36+
<TabViewItem v-for="(tab, i) in tabs" :key="i + tab.title" :title="tab.title">
37+
<Label text="tab.text" />
38+
</TabViewItem>
39+
</TabView>
40+
</GridLayout>
3941
</StackLayout>
4042
</Page>
4143
</Frame>

samples/app/app-with-tabs.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const Vue = require('nativescript-vue')
2+
3+
Vue.config.debug = true
4+
5+
let app = new Vue({
6+
data: {
7+
activeTab: 1,
8+
tabs: [
9+
{ title: 'First Tab', text: 'im the first tab' },
10+
{ title: 'Second Tab', text: 'im the second tab' },
11+
{ title: 'Third Tab', text: 'im the third tab' }
12+
]
13+
},
14+
15+
template: `
16+
<Frame>
17+
<Page>
18+
<ActionBar title="test">
19+
<StackLayout orientation="horizontal" horizontalAlignment="center">
20+
<Image src="res://icon" style="width: 30; height: 30; vertical-align: center; margin-right: 10;" />
21+
<Label style="font-size: 20; vertical-align: center;">
22+
<FormattedString>
23+
<Span text="Tabs" fontWeight="Bold" />
24+
<Span text="Navigation" />
25+
</FormattedString>
26+
</Label>
27+
</StackLayout>
28+
</ActionBar>
29+
<StackLayout>
30+
<Label :text="activeTab" />
31+
<Button text="Click me!" @tap="tabs.push({title: 'added', text: 'added tab'})" />
32+
<button text="Go to last!" @tap="activeTab = tabs.length - 1" />
33+
34+
<GridLayout>
35+
<Tabs v-model="activeTab">
36+
<TabStrip>
37+
<TabStripItem v-for="(tab, i) in tabs" :key="i + tab.title" :title="tab.title"></TabStripItem>
38+
</TabStrip>
39+
40+
<TabContentItem v-for="(tab, i) in tabs" :key="i + tab.title">
41+
<Label text="tab.text" />
42+
</TabContentItem>
43+
</Tabs>
44+
</GridLayout>
45+
</StackLayout>
46+
</Page>
47+
</Frame>
48+
`
49+
})
50+
51+
app.$start()

0 commit comments

Comments
 (0)
0