Initially at first screen,
const appLaunchedListener = Navigation.events().registerAppLaunchedListener(() => {
Navigation.setRoot({
root: {
component: {
name: 'StartScreen',
}
}
});
});
Then, using Navigation.push(...) to new page, at this point onwards I want to start using bottomTabs.
I have tried this at NewScreen:
Navigation.setRoot({
root: {
bottomTabs: {
children: [
{
stack: {
children: [{
component: {
name: 'NewScreen',
},
}],
options: {
bottomTab: {
text: 'NEW',
icon: {
scale: 15,
uri: 'new_grey'
},
selectedIcon: {
scale: 15,
uri: 'new_gold'
},
}
},
},
},
{
stack: {
children: [{
component: {
name: 'NotificationScreen',
},
}],
options: {
bottomTab: {
text: 'NOTIFICATION',
icon: {
scale: 15,
uri: 'notification_grey'
},
selectedIcon: {
scale: 15,
uri: 'notification_gold'
},
}
},
},
},
]
}
}
});
With my codes now, the bottom tabs does not appear.
How can I achieved my expceted result?
With V1, I can just use these handler: startSingleScreenApp(...) & startTabBasedApp(...)
The codes provided already worked fine. The problem lies in where to put the codes.
You can call the Navigation.setRoot(...) again in any of your screen but it should be inside of the exported class.
Like this:
...
export default class NewScreen {
constructor(props) {
super(props);
}
startTabScreen = () => {
const tabs = [{ ... }];
Navigation.setRoot({
root: {
bottomTabs: {
children: tabs
}
}
});
}
componentDidMount() {
this.startTabScreen();
}
...
}
Related
I have the problem with my navigation bar indicator(blue underline on the screenshot below)
Indicator works fine, but when you open page first time(or reload) indicator doesn't appear and there is an error in console: Active link not found.. I think, the reason of this behaviour is that the router is not fully loaded when the mounted event is called.
My Navbar component's code:
<template>
<nav>
<RouterLink to="/"><img :src="logo" alt="Logo" /></RouterLink>
<div class="navigationwrapper">
<ul class="links" #mouseleave="fixIndicator">
<li v-for="({ route, name, routeName }, index) in navLinks" #mouseenter="moveIndicator" :route-name="routeName" ref="navigationLinks">
<RouterLink :to="route">{{ name }}</RouterLink>
</li>
</ul>
<span id="indicator"></span>
</div>
</nav>
</template>
<script>
import { animate } from "motion";
import { RouterLink } from "vue-router";
import logo from "../assets/img/logo.png";
export default {
name: "Navbar",
data() {
return {
logo: logo,
navLinks: [
{
route: "/",
routeName: "home",
name: "Home",
},
{
route: "/about",
routeName: "about",
name: "About",
},
{
route: "/team",
routeName: "team",
name: "Team",
},
{
route: "/demo",
routeName: "demo",
name: "Demo",
},
],
};
},
methods: {
moveIndicator(e) {
console.log(this.activeLink());
const node = e.target;
const nodeLeft = node.offsetLeft;
const nodeWidth = node.offsetWidth;
animate("#indicator", { width: `${nodeWidth}px`, left: `${nodeLeft}px` }, { duration: 0.2, easing: "ease-in-out" });
},
fixIndicator() {
const node = this.activeLink();
if (node == null) {
console.error("Active link not found.");
return;
}
const nodeLeft = node.offsetLeft;
const nodeWidth = node.offsetWidth;
animate("#indicator", { width: `${nodeWidth}px`, left: `${nodeLeft}px` }, { duration: 0.2, easing: "ease-in-out" });
},
activeLink() {
return this.$refs.navigationLinks.find((link) => {
return link.getAttribute("route-name") == this.$route.name;
});
},
},
mounted() {
this.fixIndicator();
},
};
</script>
I think that some kind of event after full router load could solve the problem, but I don't know of one and also haven't found either.
Library I used for animation: https://motion.dev
One solution to this issue would be to move the call to this.fixIndicator from the mounted hook to the beforeRouteEnter hook in the route component that is being rendered. The beforeRouteEnter hook is called before a route is entered, after the route's components have been resolved, so it would be a good place to update the active link indicator.
I have done something like this and it is not working, is it right way to call that event? There is no console.log, so the function doesn't even execute.
export default {
name: "Navbar",
beforeRouteEnter(to, from, next) {
console.log("test");
this.fixIndicator();
},
data() {
return {
logo: logo,
navLinks: [
{
route: "/",
routeName: "home",
name: "Home",
},
{
route: "/about",
routeName: "about",
name: "About",
},
{
route: "/team",
routeName: "team",
name: "Team",
},
{
route: "/demo",
routeName: "demo",
name: "Demo",
},
],
};
},
methods: {
moveIndicator(e) {
const node = e.target;
const nodeLeft = node.offsetLeft;
const nodeWidth = node.offsetWidth;
animate("#indicator", { width: `${nodeWidth}px`, left: `${nodeLeft}px` }, { duration: 0.2, easing: "ease-in-out" });
},
fixIndicator() {
const node = this.activeLink();
if (node == null) {
console.error("Active link not found.");
return;
}
const nodeLeft = node.offsetLeft;
const nodeWidth = node.offsetWidth;
animate("#indicator", { width: `${nodeWidth}px`, left: `${nodeLeft}px` }, { duration: 0.2, easing: "ease-in-out" });
},
activeLink() {
return this.$refs.navigationLinks.find((link) => {
return link.getAttribute("route-name") == this.$route.name;
});
},
},
};
I am using the vue wrapper for jexcel and am attempting to trigger the undo function from the toolbar computed field. I cannot seem to access the instance of the spreadsheet. it throws a this.undo is undefined error
<template lang="html">
<div class="wrapper-jexcel">
<button class="" #click="getData(jExcelObj)">Data</button>
<button class="" #click="jExcelObj.undo()">Undo</button>
<input
type="button"
value="Add new row"
#click="jExcelObj.insertRow()"
/>
<div id="spreadsheet" ref="spreadsheet"></div>
</div>
</template>
import jexcelStyle from "jexcel/dist/jexcel.css"; // eslint-disable-line no-unused-vars
import jexcel from "jexcel"; // eslint-disable-line no-unused-vars
import db from '#/firebase/init'
import firebase from 'firebase'
export default {
name: "workbook",
data() {
return {
workbookid: this.$route.params.workbookid,
myCars: [],
columns: [
{ type: "text", title: "Car", width: "120px" },
{
type: "dropdown",
title: "Make",
width: "250px",
source: ["Alfa Romeo", "Audi", "BMW", "Honda", "Porshe"]
},
{ type: "calendar", title: "Available", width: "250px" },
{ type: "image", title: "Photo", width: "120px" },
{ type: "checkbox", title: "Stock", width: "80px" },
{
type: "numeric",
title: "Price",
width: "120px",
mask: "$ #.##,00",
decimal: ","
},
{ type: "color", width: "100px", render: "square" }
]
};
},created() {
this.getworkbook()
},
methods: {
onchange(){
console.log('change');
},
insertRowc() {
console.log(this);
// this.spreadsheet.insertRow();
},
undo(){
console.log('test');
jExcelObj.undo();
},
getData(payload) {
console.log(this.myCars);
console.log(payload);
// this.myCars = payload.data
}
},
computed: {
jExcelOptions() {
var self = this;
return {
data: this.myCars,
columns: this.columns,
search: true,
//fullscreen: true,
minDimensions: [20, 40],
defaultColWidth: 100,
allowComments: true,
toolbar: [
{ type:'i', content:'undo', onclick:function() { return jExcelObj.undo(); } },
{ type:'i', content:'redo', onclick:function() { this.redo(); } },
{ type:'i', content:'save', onclick:function () { test.download(); } },
{ type:'select', k:'font-family', v:['Arial','Verdana'] },
{ type:'select', k:'font-size', v:['9px','10px','11px','12px','13px','14px','15px','16px','17px','18px','19px','20px'] },
{ type:'i', content:'format_align_left', k:'text-align', v:'left' },
{ type:'i', content:'format_align_center', k:'text-align', v:'center' },
{ type:'i', content:'format_align_right', k:'text-align', v:'right' },
{ type:'i', content:'format_bold', k:'font-weight', v:'bold' },
{ type:'color', content:'format_color_text', k:'color' },
{ type:'color', content:'format_color_fill', k:'background-color' },
]
};
}
},
mounted: function() {
//console.log(this.jExcelOptions);
//console.log(this.$refs["spreadsheet"]);
const jExcelObj = jexcel(this.$refs["spreadsheet"], this.jExcelOptions);
// Object.assign(this, jExcelObj); // pollutes component instance
Object.assign(this, { jExcelObj }); // tucks all methods under jExcelObj object in component instance
// console.log(this.jExcelObj);
}
};
should i be passing the instance into the computed method? I am struggling to understand how to manage instances of a wrapper plugin and accessing the methods.
You can get the instance using that:
var yourTableInstance = document.getElementById('spreadsheet').jexcel;
yourTableInstance.undo();
yourTableInstance.getData();
mounted: function() {
let spreadsheet = jspreadsheet(this.$el, options);
Object.assign(this, spreadsheet);
}
I am having a bit of trouble implementing the sideMenu to the following code: (see the startTabs).
I call this after "login" is clicked on my root screen. The root screen looks like the following:
Navigation.setRoot({
root: {
stack: {
children: [{
component: {
name: "navigation.playground.WelcomeScreen",
passProps: {
text: "stack with one child"
},
alignment: "center",
options: {
topBar: {
visible: true,
title: {
text: "main screen"
}
}
}
}
}]
}
}
});
const startTabs = () => {
Promise.all([
Icon.getImageSource("md-map", 30),
Icon.getImageSource("ios-share-alt", 30)
]).then(sources => {
Navigation.setRoot({
root: {
bottomTabs: {
children: [{
stack: {
children: [{
component: {
name: "navigation.playground.FindPlaceScreen",
options: {
bottomTab: {
text: "Find Place",
icon: sources[0]
},
topBar: {
visible: true,
title: {
text: "Find Place"
}
}
}
}
}
]
}
},
{
stack: {
children: [{
component: {
name: "navigation.playground.SharePlaceScreen",
options: {
bottomTab: {
text: "Share Place",
icon: sources[1]
},
topBar: {
// visible: true,
title: {
text: "Share Place"
}
}
}
}
}]
}
}
]
}
}
});
});
};
Now in order for me to implement sideMenu after login, Would I implement it in the "startTabs"? or elsewhere?
Solved this. Sorry I am a new programmer, so I had a spelling mistake in my sideDrawer component where "render" was spelled "redner". Took me the longest time to figure this out!!!
Otherwise the code I pasted in initial question is correct (for anyone who looks at this for reference). Thanks!
I've been trying to learn react and I've been using the Wix Navigation.
I want the first screen the user lands on to be a screen that is not in the bottom tabs selection.
They will land on Screen0 and have the ability to navigate to Screen1 and Screen2 from the tabs.
So my question is, how do I set the landing screen to a be screen that isn't in the bottom tabs?
Navigation.setRoot({
root: {
bottomTabs: {
children: [
{
stack: {
children: [{
component: {
name: "Screen1",
},
}],
options: {
bottomTab: {
text: 'Screen1',
icon: require('../assets/icons/Screen1.png')
}
}
}
},
{
stack: {
children: [{
component: {
name: "Screen2",
},
}],
options: {
bottomTab: {
text: 'Screen2',
icon: require('../assets/icons/Screen2.png')
}
}
}
}
]
}
}
})
I'd like to import a helper class rather than inlining the logic inside my component. I get the following error:
http://eslint.org/docs/rules/no-unused-vars 'NavbarService' is defined but never used
/services/NavbarService.js
class NavbarService {
constructor (init) {
this.init = init;
}
static applications () {
return [
{ name: 'Administration' },
{ name: 'Standard' }
];
}
static views () {
return [
{ name: 'Providers', path: '/providers' },
{ name: 'Authorities', path: '/authorities' },
{ name: 'Services', path: '/services' },
{ name: 'Codes', path: '/codes' }
];
}
}
/components/Navbar.vue
import NavbarService from '../services/NavbarService.js';
export default {
data () {
return {
versionIsVisible: false,
version: '2.0.0',
applications: NavbarService.applications(),
views: NavbarService.views()
};
},
methods: {
showApplications: function () {
this.applications = NavbarService.applications();
this.views = [];
return;
}
}
};
Following Roy J's suggestion, I changed /services/NavbarService.js to:
export default {
applications: function () {
return [
{ name: 'Administration' },
{ name: 'Standard' }
];
},
views: function () {
return [
{ name: 'Providers', path: '/providers' },
{ name: 'Authorities', path: '/authorities' },
{ name: 'Services', path: '/services' },
{ name: 'Codes', path: '/codes' }
];
}
};