Can I use BottomNavigation with components? - vue.js

I'm trying to display a bottom navigation, in which the TabContent comes from components. Now, with the following code I can't get the tab content to show, and I don't get any errors.
PageContainer.vue:
<template>
<BottomNavigation selectedIndex="1" class="tab__container" #loaded="loaded">
<TabStrip>
<TabStripItem class="tab">
<Label :text="text.groups" />
</TabStripItem>
<TabStripItem class="tab">
<Label :text="text.mail" />
</TabStripItem>
</TabStrip>
<TabContentItem>
<GroupsScreen />
</TabContentItem>
<TabContentItem>
<MailScreen />
</TabContentItem>
</BottomNavigation>
</template>
<script >
import GroupsScreen from './GroupsScreen';
import MailScreen from './MailScreen';
export default {
components: {
GroupsScreen,
MailScreen,
},
data() {
return {
text: {
groups: 'Groepen',
mail: 'Berichten',
},
}
},
}
</script>
GroupsScreen.vue:
<template>
<Frame #loaded="loaded">
<ActionBar :title="text.groups" />
<StackLayout class="page">
<Label v-if="groupsLoading" text="Loading"></Label>
</StackLayout>
</Frame>
</template>
Is this even possible, or am I trying to do something that should be done in another way?

The hierarchy is always,
Frame
Page
Content (Layouts, ScrollView etc.,)
A Frame can only host a Page, it can not directly host Content. You need Frame only if you want to navigate within that particular container.
So your primary issue was not wrapping your BottomNavigation with a Page element.
Updated Playground

Related

Showing array data in nativescript-vue view modal component

I want to create a modal component from the parent and fill data in that modal in a listview
If the component was already created, I don't have a problem, but I want the component created in that parent page
template>
<Page class="page">
<ActionBar title="Modal Data" class="action-bar"></ActionBar>
<ScrollView>
<StackLayout class="m-20">
<Button text="Button" #tap="goToDetailPage" />
</StackLayout>
</ScrollView>
</Page>
</template>
<script>
const Detail = {
template: `
<Page>
<ActionBar title="Asal Ikan" />
<StackLayout>
<ListView class="list-group" for="mylist in mylists" style="height:600px;">
<v-template>
<FlexboxLayout flexDirection="row" class="list-group-item">
<Label :text="mylist.name" style="width:100%;" #tap="closeModal" />
</FlexboxLayout>
</v-template>
</ListView>
</StackLayout>
</Page>
`
};
export default {
data() {
return {
mylists: [{
code: "SL",
name: "Sinjai"
},
{
code: "MK",
name: "Makasar"
}
]
};
},
methods: {
goToDetailPage() {
this.$showModal(Detail);
}
}
};
</script>
Data from my List is not showing.
here the playground link :
https://play.nativescript.org/?template=play-vue&id=WlzgRU&v=104
There are a number of things you may want to improve / correct in your code.
Detail is a standalone component, it won't have access to the data in your Master (HelloWorld) component. You should pass mylists in props if you like to access the same data.
A Page can only be hosted within a Frame and a valid Page can only have ActionBar. Since you haven't defined a Frame in your Detail component, it won't be valid.
With ListView use itemTap event instead of adding event listeners to individual component.
Updated Playground

nativescript-youtubeplayer toggle fullscreen in nativescript-vue app

I'm trying to do a fullscreen in youtube player from the plugin triniwiz/nativescript-youtubeplayer in my nativescript-vue application on android device but I'm unable to achieve so.
I have following code:
<template>
<Page actionBarHidden="true" class="page" >
<GridLayout orientation="vertical" width="100%" height="100%" columns="*" rows="*,auto">
<StackLayout col="0" row="0" backgroundColor="#f8f8f8">
<StackLayout backgroundColor="#44557f">
<Label :text="name" class="font-weight-bold"
color="#FFFFFF" padding="15" fontSize="20" textWrap="true"></Label>
</StackLayout>
<ScrollView orientation="vertical" height="100%">
<ScrollView orientation="vertical">
<StackLayout class="home-panel">
<YoutubePlayer ref="player" :src="videoLink.substring(17)" apiKey="**********" isFullScreen="true"/>
</StackLayout>
</ScrollView>
</ScrollView>
</StackLayout>
</GridLayout>
</Page>
</template>
<script>
export default {
props: ['videoLink','name','id'],
mounted() {
let player = this.$refs.player
player.toggleFullscreen();
}
}
</script>
But I'm getting an error stating
toggleFullscreen() not found
When you access an element via Ref, the return value will be a Vue element. You should access the nativeView to gain access to the actual element.
<script>
export default {
props: ['videoLink','name','id'],
mounted() {
let player = this.$refs.player.nativeView;
player.toggleFullscreen();
}
}
</script>

Tabview not showing data in first tab in nativescript-vue

I have place a Tabview in my component with 2 tabs. In the first i'm loading some data from an API and render a ListView with data. In the other tab i'm showing some other data.
The data from the API is not showing when the component is first show, I have tab press the tab 2 and then tab 1 and the data is then shown.
<template>
<Page class="page">
<TabView :selectedIndex="selectedIndex"
#selectedIndexChange="indexChange">
<TabViewItem title="Tab 1">
<StackLayout orientation="vertical">
<ListView height="90%" class="list-group"
for="item in allCategories">
<v-template>
<StackLayout class="list-group-item"
orientation="horizontal">
<Image :src="item.imageURL"
stretch="aspectFill" class="categoryImage"
width="75" height="75">
</Image>
<Label class="categoryText"
:text="item.element.groupText"/>
</StackLayout>
</v-template>
</ListView>
</StackLayout>
</TabViewItem>
<TabViewItem title="Tab 2">
<Label text="Content for Tab 2" />
</TabViewItem>
</TabView>
</Page>
</template>
created: function () {"url").then(result => {
result.data.forEach(element => {
var imageURL = element.image.imageURL;
this.allCategories.push({element, imageURL })
});
}, error => {
console.log(error);
});
},
I want the data to be show when the component is first show because the tab 1 is marked as the showing tab. Any ideas?
Here is an example in the playground: https://play.nativescript.org/?template=play-vue&id=9Fk7AS&v=10
The answear is in the issue I commited for the repository in github: https://github.com/nativescript-vue/nativescript-vue/issues/515
Just change:
<TabView :selectedIndex="selectedIndex" #selectedIndexChange="indexChange">
To:
<TabView>

Nativescript vue dismiss / hide Android keyboard

I'm using the excellent https://github.com/tjvantoll/nativescript-IQKeyboardManager on iOS, which has a 'done' button (effectively a close button). However, for Android softkeyboard there is no such thing... All the solutions to hide a keyboard suggest referencing the original element which triggered the keyboard - an impractical solution...
I found this forum post on how to dismiss a keyboard in nativeScript https://discourse.nativescript.org/t/unable-to-hide-keyboard/4129/9
import * as utils from "utils/utils";
import { isIOS, isAndroid } from "platform";
import * as frame from "ui/frame";
// then as a method inside your vue
methods: {
dismissSoftKeybaord() {
if (isIOS) {
frame.topmost().nativeView.endEditing(true);
}
if (isAndroid) {
utils.ad.dismissSoftInput();
}
},
dimissSoftKeyboard should be attached to the outside / top element - eg page... Then, when clicking outside of a form field (TextField or TextView) the keyboard will be hidden / dismissed.
<Page #tap="dismissSoftKeybaord()">
Here is the code as a handy mixin:
import * as utils from "utils/utils";
import { isIOS, isAndroid } from "platform";
import * as frame from "ui/frame";
export default {
methods: {
dismissSoftKeybaord() {
if (isIOS) {
frame.topmost().nativeView.endEditing(true);
}
if (isAndroid) {
utils.ad.dismissSoftInput();
}
},
}
};
I do have a bit of an issue with layout, in that some elements wrap other elements so I've had to apply dismissSofteyboard in a few places - but it works....
<template>
<Page class="page" statusBarStyle="dark" backgroundSpanUnderStatusBar="true">
<ActionBar backgroundColor="#253945" color="#ffffff" flat="true" #tap="dismissSoftKeybaord()">
<StackLayout orientation="horizontal">
<Label ... />
</StackLayout>
</ActionBar>
<GridLayout rows="*,60" #tap="dismissSoftKeybaord()">
<ScrollView row="0" #tap="dismissSoftKeybaord()">
<StackLayout class="logFormWrapper">
<StackLayout class="input-field" marginBottom="20" >
<TextField ... />
</StackLayout>
<StackLayout class="input-field" marginBottom="20">
<TextField ... />
</StackLayout>
...
...
</StackLayout>
</ScrollView>
<StackLayout margin="0" row="1" class="footer"></StackLayout>
</GridLayout>
</Page>
</template>
So I'm now just trying to figure out how I can adjust the layout so I don't need so many dismissSoftKeyboard #taps everywhere....

NativeScript-Vue zoom image

I am working on a basic app that has a list of items and when an item is selected its corresponding image is show in an image tag.Issue is, the images are very "wide" and hence appear very small. I am trying to somehow enable the zoom functionality on the image for the user. I checked all "stretch" options but "pinch" and "zoom" are not working. According to official documentation, i looked at decodeHeight and decodeWidth but they do not appear to be working as well.
I appreciate any help i can get, Following is the code:
<template>
<Page class="page">
<ActionBar title="Home" class="action-bar" />
<ScrollView>`enter code here`
<StackLayout class="home-panel">
<Image :src="img_src" strech="AspectFill"/>
<ListView for="images in img_data" #itemTap="onButtonTap" style="height:200vh">
<v-template>
<Label :text="images.name" />
</v-template>
</ListView>
<!-- <Button text="Button" #tap="onButtonTap" /> -->
</StackLayout>
</ScrollView>
</Page>
</template>
<script>
export default {
methods: {
onButtonTap(event) {
console.log(event.index);
this.img_src = "~/components/" + this.img_data[event.index].image;
}
},
data() {
return {
img_src: "",
img_data: [
{ name: "Iron Man", image: "iron_man.png" },
{ name: "super man", image: "super_man.png" },
{ name: "Batman", image: "batman.png" },
{ name: "Flash", image: "flash.png" },
]
};
}
};
</script>
<style scoped>
.home-panel {
vertical-align: top;
padding-top: 20;
font-size: 20;
margin: 15;
}
.description-label {
margin-bottom: 15;
}
</style>
First, install nativescript-image-zoom plugin:
tns plugin add nativescript-image-zoom
Then globally register the ImageZoom element in your main.js:
Vue.registerElement('ImageZoom', () => require('nativescript-image-zoom').ImageZoom);
Now you can use it as a global component anywhere in your app you want.
<ImageZoom v-if="ifStatement"
:src="imageSrc"
class="main-image" />
Keep in mind that while global registration of the component doesn't hurt the performance, it prevents you from lazy loading the element.
Install the plugin by running the following command
tns plugin add nativescript-image-zoom
Replace your Image tag with this custom component
<StackLayout class="home-panel">
<ui:ImageZoom :src="img_src" strech="AspectFill"/>
<ListView for="images in img_data" #itemTap="onButtonTap" style="height:200vh">
<v-template>
<Label :text="images.name" />
</v-template>
</ListView>
<!-- <Button text="Button" #tap="onButtonTap" /> -->
</StackLayout>
Don't forget to add xmlns to your Page element.
xmlns:ui="nativescript-image-zoom"
In case you have any another question, please don't hesitate to ask.