Nativescript vue tooltip use - vue.js

I'm using nativescript vue
I want to run this tooltip.
code like in tutorial is not working:
<Button text="Get Json Data" id="tool" ref="tooltip" #tap="getData" class="btn btn-primary m-t-20"></Button>
I made button like this and in created trying to make it working but
created() {
let tipref = this.$refs.tooltip;
let tippref = this.$refs.page.tooltip;
//new ToolTip(this.nativeView.topmost().tip,{text:"Text"});
//const tip = new ToolTip(this.nativeView.tipref,{text:"Some Text"});
new ToolTip(tipref,{text:"Some Text"});
},
still not working: TypeError: Cannot read property 'tooltip' of undefined
TypeError: Cannot read property 'nativeView' of undefined
Can't figure out how to do it.
The code from the answer How to create a floating help layout? is not working too.

In order to access the NativeScript View via ref, you should do this.$refs.tooltip.nativeView. Also wait for the loaded event of the element to make sure it's ready to use.
<template>
<Page class="page">
<ActionBar title="Home" class="action-bar"/>
<ScrollView>
<StackLayout class="home-panel">
<Button
text="Get Json Data"
ref="tooltip"
class="btn btn-primary m-t-20"
#loaded="onLoaded"
></Button>
</StackLayout>
</ScrollView>
</Page>
</template>
<script>
export default {
data() {
return {};
},
methods: {
onLoaded: function(args) {
const ToolTip = require("nativescript-tooltip").ToolTip;
const tip = new ToolTip(args.object, {
text: "Some Text",
backgroundColor: "pink",
textColor: "black"
});
tip.show();
}
}
};
</script>

Related

Popup on top of each other VUEJS3

I want to put several Buttons, each one opening a different Popup. A Popup would print data concerning its Button.
I have a Popup.vue component :
<template>
<div class="popup">
<div class="popup-inner">
<slot />
<Button class="popup-close" #click="TogglePopup()">
Close
</Button>
</div>
</div>
</template>
<script>
export default {
props: ['TogglePopup']
}
</script>
And in another .vue I call it like that :
<template>
<div v-for="infoItem in data" :key="infoItem.name"> // loop to create several buttons
<Button
icon="pi pi-eye"
#click="() => TogglePopup('buttonTriggerDetail')">
</Button>
<Popup
v-if="popupTriggers.buttonTriggerDetail"
:TogglePopup="() => TogglePopup('buttonTriggerDetail')"
>
{{ infoItem.control }}
</Popup>
</div>
</template>
<script>
import ...
export default {
computed: {
data() {
return this.$store.state.data;
},
},
mounted() {
this.$store.dispatch("getData");
},
setup() {
const popupTriggers = ref({
buttonTriggerDetail: false
});
const TogglePopup = (trigger) => {
popupTriggers.value[trigger] = !popupTriggers.value[trigger];
};
return {
Popup,
TogglePopup,
popupTriggers,
};
},
};
</script>
So it prints several Button but when I click on one, it don't open the Popup with the data of this Button, it always prints the data of the last Button. I think in reality it places all the pop up on top of each others.
How can I do to open only the good Popup with the good data ?
Thanks
The mistake is that you are rendering 3 popups when you need only one with certain props. Think of your popups as of tabs: let popup be rendered by clicking on certain button and pass in props you need, for example:
<template>
<div v-for="infoItem in data" :key="infoItem.name"> // loop to create several buttons
<Button
icon="pi pi-eye"
#click="clickHandler">
</Button>
</div>
<Popup
v-if="popupTriggered"
:TogglePopup="() => TogglePopup('buttonTriggerDetail')"
>
{{ data[currentActiveItem].control }}
</Popup>
</template>
<script>
import ...
export default {
data () {
currentActiveItem: 0,
popupTriggered: false
},
methods: {
clickHandler (index) {
this.popupTriggered = true
this.currentActiveItem = index
}
}
... // other component data
};
</script>
I wrote my example in Vue 2 style because I haven't worked with Composition API yet but I hope you got the idea.

How to show a hidden div by clicking on another div (button) in Vue?

I am trying to show the loading div that's normally hidden after clicking a confirm button, even after changing the hidden value on click.
here is my code:
<div class="form-btns">
<button type="button" class="btns full-width" v-on:click="submitPhoneNumber(); isHidden = false">
{{t('confirmNumber')}}
</button>
<loader title="" v-if="!isHidden"></loader>
<button type="button" class="btns hyperlink">
{{t('accountRecovery')}}
</button>
</div>
data() {
return {
isHidden: true,
};
Your code is a little funky. Get rid of how you're trying to set the value directly in the template HTML and set it in your function in the methods. So your new code would be:
<div class="form-btns">
<button type="button" class="btns full-width" v-on:click="submitPhoneNumber()">
v {{t('confirmNumber')}}
</button>
<loader title="" v-if="!isHidden"></loader>
<button type="button" class="btns hyperlink">
{{t('accountRecovery')}}
</button>
</div>
Then in your methods just toggle the value like this:
data() {
return {
isHidden: true,
}
},
methods: {
submitPhoneNumber() {
this.isHidden = false; // I would probably rename this to isLoading and invert the logic
// Other stuff...
}
}
You should change the isHidden value inside the submitPhoneNumber, either as below, or with a dedicated function that you call in the first one.
let app = new Vue({
el: '#app',
data: {
isHidden: true
},
methods: {
submitPhoneNumber() {
this.isHidden = false;
// Simulate an API response after 3s to hide the loader
setTimeout(() => { this.isHidden = true; }, 3000);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type="button" #click="submitPhoneNumber()">
Submit button
</button>
<p v-if="!isHidden">Loading...</p>
</div>

How to handle navigation on a Nativescript Vue app?

I'm having issue understanding how navigation works using NativeScript Vue. I started yesterday and can't seem to make it work. It says my AppDrawer component is recursive.
The main frame contain a page, which contain the menu and the action bar. If I click on something, it loads the new page in the main frame and reload the menu and the action bar. Or does people just use a frame in the middle to load the pages without having to redraw the menu/drawer? Doing so, how would I change the data in the actionbar or the drawer from inside the frame? I'm guessing using Vuex, but I'm not quite sure what is the optimal approach when designing an android app.
Sorry if I get some terminology wrong.
nav/AppDrawer.vue:
<template>
<StackLayout ~drawerContent backgroundColor="#444">
<Label class="drawer-header" text="Drawer" />
<Label class="drawer-item" text="Accueil" #tap="btnHome()" />
<Label class="drawer-item" text="Item 2" #tap="btnAdd2()" />
<Label class="drawer-item" text="Item 3" #tap="btnHistory()" />
</StackLayout>
</template>
<script>
// Load pages
import App from "../App";
import Add2 from "../Add2";
import History from "../History";
export default {
components: {},
methods: {
btnHome() {
this.$navigateTo(App);
},
btnAdd2() {
this.$navigateTo(Add2);
},
btnHistory() {
this.$navigateTo(History);
},
},
};
</script>
App.vue:
<template>
<Page>
<ActionBar>
<GridLayout width="100%" columns="auto, *">
<Label
text="MENU"
#tap="$refs.drawer.nativeView.showDrawer()"
col="0"
/>
<Label class="title" text="Title" col="1" />
</GridLayout>
</ActionBar>
<RadSideDrawer ref="drawer">
<AppDrawer />
<GridLayout ~mainContent columns="*" rows="*">
<TextView editable="false">
<FormattedString>
<Span :text="msg" />
</FormattedString>
</TextView>
</GridLayout>
</RadSideDrawer>
</Page>
</template>
<script>
import AppDrawer from "./nav/AppDrawer.vue";
import { device } from "tns-core-modules/platform";
export default {
components: {
AppDrawer,
},
data() {
return {
msg:
"Vous n'êtes pas connecté. Les téléversements seront assigné avec l'ID: " +
device.uuid,
};
},
methods: {},
};
</script>
History.vue:
<template>
<Frame>
<Page>
<ActionBar>
<GridLayout width="100%" columns="auto, *">
<Label
text="MENU"
#tap="$refs.drawer.nativeView.showDrawer()"
col="0"
/>
<Label class="title" text="History" col="1" />
</GridLayout>
</ActionBar>
<RadSideDrawer ref="drawer">
<AppDrawer />
<GridLayout ~mainContent columns="*" rows="*">
<TextView editable="false">
<FormattedString>
<Span text="testing 1, 2" />
</FormattedString>
</TextView>
</GridLayout>
</RadSideDrawer>
</Page>
</Frame>
</template>
<script>
import AppDrawer from "./nav/AppDrawer.vue";
export default {
components: {
AppDrawer,
},
data() {
return {};
},
methods: {},
};
</script>
EDIT:
Ok, I understand the problem is that I import AppDrawer in App, so the App page have a menu. And I then import App in AppDrawer, because I want a "Home" button in the menu, so the user can return the the main page/screen.
This create a loop. I still don't understand how people import menus on each page and still have each page imported in the menu so user can be redirected on that page.
Based on the answer below, I tried:
<script>
export default {
components: {
App: () => import("../App.vue"),
AddProduct: () => import("../Add2.vue"),
History: () => import("../History.vue")
},
methods: {
btnHome() {
this.$navigateTo(App);
},
btnAdd2() {
this.$navigateTo(Add2);
},
btnHistory() {
this.$navigateTo(History);
}
}
};
</script>
But I get JS: [Vue warn]: Error in v-on handler: "ReferenceError: Add2 is not defined".
You are importing AppDrawer in App, and importing App in AppDrawer.vue, this import loop never end, you have to use lazyloading if you need do this (Although you imported and didnt use App componenet):
// in AppDrawer.vue
components: {
'App': () => import('../App.vue')
},

Binding method to an option in a component in vue.js

I'm pretty new to Vue and are using a litebox component which I want to customize a bit so the lightbox gallery starts on different images depending on which button is pressed. I have succeeded to solve this by using a click event which I'm binding to an option in the litebox component. Since I am new to Vue. I'm just wondering if this is a good way of solving something like this or if there is a better way?
<template>
<div id>
<button type="button" #click="show(); start1();">Show Litebox start 1</button>
<button type="button" #click="show(); start2();">Show Litebox start 2</button>
<vue-litebox v-if="showLitebox" :startAt="start" :items="images" #close="hide"></vue-litebox>
</div>
</template>
<script>
import VueLitebox from "vue-litebox";
export default {
components: { VueLitebox },
data() {
return {
images: [
"https://placekitten.com/400/400",
"https://placekitten.com/400/401",
{
title: "My image title",
src: "https://placekitten.com/400/402"
}
],
showLitebox: false,
start: 0
};
},
methods: {
show() {
this.showLitebox = true;
},
hide() {
this.showLitebox = false;
},
start1() {
this.start = 1
},
start2() {
this.start = 2
}
}
};
</script>
Here is the code on code sandbox:
https://codesandbox.io/s/9ok4y6lopo?fontsize=12
Templates should be as logic-free as possible, besides, there is no need to chain methods this way because you can always pass parameters to methods, like this:
// in your template
<button
type="button"
#click="show(1)"
>
Show Litebox start 1
</button>
// in methods section
show (start = 1) { // defaults to 1
this.show = true;
this.start = start;
}
By the way, it seems like v-show would be a better choice than v-if for vue-litebox component (see documentation).

Can't Access Props in NativeScript Vue Modal

I'm using a modal to show a listView and I want to pass the list into the modal as an array. I call the modal, like so:
this.$showModal(Picker, { props: { list: [
{ name: "Item 1" },
{ name: "Item 2" },
{ name: "Item 3" }
]}});
The modal loads fine, and I can see the props in the modal when I console.log
created: function(){
console.log(this.list);
},
However, I can't access the props in the template or loop over them.
<ListView for="item in listOfItems">
<v-template>
<Label :text="item.name" class="listItem" />
</v-template>
</ListView>
I have also tried:
<ListView :for="item in $props.list">
My full code for the modal component is below:
<template>
<Page>
<ListView for="item in listOfItems">
<v-template>
<Label :text="item.name" class="listItem" />
</v-template>
</ListView>
</Page>
</template>
<script>
export default {
props: ["list"],
created: function(){
console.log(this.list);
},
data(){
return {
listOfItems: this.list
}
}
}
</script>
What am I doing wrong?
Change <ListView for="item in listOfItems"> to <ListView for="item in list">
Don’t know why, but when I changed the
data() return {
so that the variable names are the same,
{animals: animals,
vegetables: vegetables }
it worked.
Didn’t have to do this for strings or integers, just objects.
<ListView for="item in $props.list">
Remove colon?
I'm taking care of removing unnecessary : of head of for and refering to $props property when coding with NativeScript-Vue.