How to handle navigation on a Nativescript Vue app? - vue.js

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')
},

Related

How to combine two values from child components with an event?

I can't assign data from child component.
I am simply trying to implement emitting a specific value with an event
Child component is:
<template>
<StackLayout orientation="vertical" width="210" height="210"
backgroundColor="blue" color="white">
<Label text="Father" row="0" col="1"
class="h2 text-center p-t-5 text-primary" />
<ListPicker :items="maleName" v-model="maleIndex" row="1" col="1"
#selectedIndexChange="selectedIndexofFatherChanged" />
</StackLayout>
</template>
<script>
export default {
data() {
return {
maleName: [
"Rey",
"Antonia",
"Victor",
"Lincoln",
],
maleIndex: 0
};
},
methods: {
selectedIndexofFatherChanged() {
this.$emit("fatherChanged", this.fatherName);
// console.log("changed to: " + this.fatherName);
}
},
computed: {
fatherName() {
return this.maleName[this.maleIndex];
}
}
};
</script>
and Parent Component is:
<template>
<Page>
<ActionBar title="Choose Parent" />
<GridLayout columns="*, *" rows="*,90">
<SelectMother col="0" #motherChanged="onMotherChanged">
</SelectMother>
<SelectFather col="1" #fatherChanged="onFatherChanged">
</SelectFather>
<Button text="Show Result" #tap="onButtonTap" row="2"
colSpan="2" />
</GridLayout>
</Page>
</template>
<script>
import SelectMother from "./SelectMother";
import SelectFather from "./SelectFather";
export default {
components: {
SelectMother,
SelectFather
},
data() {
return {
motherName: null,
fatherName: null
};
},
methods: {
onButtonTap() {
alert("father: " + this.fatherName + " mother: " + this
.motherName);
},
},
watch: {
onFatherChanged(nameFromComponent) {
nameFromComponent = this.fatherName;
},
onMotherChanged(nameFromComponent) {
nameFromComponent
= this.motherName;
}
},
};
</script>
When I console log payload in onFatherChanged method it turns null
How to combine father and mother and show results.
Select Father from child component
Select Mother from second child component
Assign incoming payload and Show Results
Please check {N} Playground
https://play.nativescript.org/?template=play-vue&id=Dez2fV&v=26
Instead of
onFatherChanged(payload) {
payload = this.fatherName;
console.log(payload);
},
It should be;
onFatherChanged(payload) {
this.fatherName = payload;
console.log(payload);
},

Nativescript vue tooltip use

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>

Cannot pass the fetch method information to the instance data

When I run the below code, the values inside the currencie variable are not displayed.
I cannot pass the fetch method information to the instance data. I would like to fetch the data and display it on the screen. If I use console.log I can see the data as expected.
<template>
<Page class="page">
<ActionBar title="Tela N°1" class="action-bar" />
<ScrollView>
<StackLayout class="home-panel">
<!--Add your page content here-->
<Label textWrap="true" text="Primeira tela criada usando NativeScript"
class="h2 description-label" />
<Button text="Segunda Tela" #tap="onButtonTap" />
<Button text="Terceira Tela" #tap="onButton" />
<ListView class="list-group" for="currencie in currenciess"
style="height:1250px">
<v-template>
<FlexboxLayout flexDirection="row" class="list-group-item">
<Label :text="currencie.name" class="list-group-item-heading" style="width: 60%" />
<Label :text="currencie.buy" class="list-group-item-heading"
style="width: 60%" />
</FlexboxLayout>
</v-template>
</ListView>
</StackLayout>
</ScrollView>
</Page>
</template>
<script>
import Second from "./Second";
import Third from "./Third";
const http = require("tns-core-modules/http");
const url = "https://api.hgbrasil.com/finance?key=c5239f9c";
export default {
data() {
return {
currenciess: []
};
},
mounted() {
fetch(url)
.then(response => response.json())
.then(results => {
this.currenciess = results.results.currencies.USD;
});
},
};
</script>
Change your mounted method. currenciess is an array while your results.results.currencies["USD"] is an object coming from API. I have created a playground for you here.
mounted() {
console.log("mounted");
fetch(url)
.then(response => response.json())
.then(results => {
this.currenciess.push(results.results.currencies["USD"]);
});
}

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.

this.$refs.canvas undefined in vuejs

I'm setting up a new project using vuejs3 and canvas, but I'm trapped in canvas element. Could anyone give me some advice or ideas?
In my project I got undefined with this.$refs.canvas. Also when I use document.getElementById('canvas'), I get null.
<template>
<div id="app">
<canvas
ref="canvas"
id="canvas"
class="bg"
width="400"
height="400"></canvas>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
}
},
created() {
// const canvas = this.$refs.canvas.getContext('2d')
const canvas = document.getElementById('canvas')
console.log(canvas)
},
}
</script>
It will be appreciate if anyone can give me some help.
The elements won't yet be rendered in created. Try mounted.
<template>
<div id="app">
<canvas
ref="canvas"
id="canvas"
class="bg"
width="400"
height="400"></canvas>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
}
},
mounted() {
const canvas = this.$refs.canvas.getContext('2d')
console.log(canvas)
},
}
</script>
View the Lifecycle Diagram here: https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram