NativeScript vue, vuex and urlhandler - nativescript

Edit
I'm using https://github.com/hypery2k/nativescript-urlhandler to open a deep link within my app - using NativeScript vue, and vuex. It seems that in order to get at the methods needed to do routing [$navigateTo etc] this plugin needs to be set up slightly differently from the examples given in docs.
import Vue from "nativescript-vue";
import Vuex from "vuex";
Vue.use(Vuex);
import { handleOpenURL } from 'nativescript-urlhandler';
new Vue({
mounted() {
handleOpenURL( (appURL) => {
console.log(appURL)
// Settings is the variable that equals the component - in this case settings.
this.$navigateTo(Settings);
});
},
render: h => h("frame", [h(Home)]),
store: ccStore
}).$start();
handleOpenURL needs to be called within Mounted - then you can parse out the appURL and reference the page (component) that you wish to navigate to. I have been advised against calling handleOpenURL from within router - but I'm not sure why, and it works without error - and I have access to the methods for routing... so if anyone knows if this is a bad idea - please let me know :) Thanks!
All the stuff below that I wrote before has probably confused things - I'm referencing components within my vuex store to make them easily available from the router.
This is based on a solution by https://github.com/Spacarar - it can be found here: https://github.com/geodav-tech/vue-nativescript-router-example. It's a great solution because you don't have to include every single component within each component to use in navigation - it gives an almost vue router like experience.
I'm using https://github.com/hypery2k/nativescript-urlhandler to open a deep link within my app - however, I'm having problems opening the link.
In my app.js file, I have the following:
import Vue from "nativescript-vue";
import Vuex from "vuex";
Vue.use(Vuex);
....
import { handleOpenURL } from 'nativescript-urlhandler';
import ccStore from './store/store';
handleOpenURL(function(appURL) {
// I have hardwired 'Settings' in for testing purposes - but this would be the appURL
ccStore.dispatch('openAppURL', 'Settings');
});
....
new Vue({
render: h => h("frame", [h(Home)]),
store: ccStore
}).$start();
I'm storing the route state within vuex, and have various methods which work (clicking on a link loads the component). However, handleOpenURL exists outside of vue... so I've had to access vuex directly from within the handleOpenURL method. I've created an action specifically for this case - openAppURL.. it does exactly the same thing as my other methods (although I've consolidated it).
When clicking on an app link, I am NOT taken to the page within the app. I have put a console log within openAppURL and can see it is being called, and the correct route object is returned... it just doesn't open the page. The SetTimeOut is used because nextTick isn't available from within vuex.
I am at a loss on how to get the page to appear...
const ccStore = new Vuex.Store({
state: {
user: {
authToken: null,
refreshToken: null,
},
routes: [
{
name: "Home",
component: Home
},
{
name: "Log In",
component: Login
},
...
],
currentRoute: {
//INITIALIZE THIS WITH YOUR HOME PAGE
name: "Home",
component: Home //COMPONENT
},
history: [],
},
mutations: {
navigateTo(state, newRoute, options) {
state.history.push({
route: newRoute,
options
});
},
},
actions: {
openAppURL({state, commit}, routeName ) {
const URL = state.routes[state.routes.map( (route) => {
return route.name;
}).indexOf(routeName)];
return setTimeout(() => {
commit('navigateTo', URL, { animated: false, clearHistory: true });
}, 10000);
},
....
}
etc....

I have been advised to post my findings as the answer and mark it as correct. In order to use nativescript-urlhandler with vue, you must initialise the handler from within vue's mounted life cycle hook. Please see above for greater detail.
import Vue from "nativescript-vue";
import Vuex from "vuex";
Vue.use(Vuex);
import Settings from "~/components/Settings";
import { handleOpenURL } from 'nativescript-urlhandler';
new Vue({
mounted() {
handleOpenURL( (appURL) => {
console.log(appURL) // here you can get your appURL path etc and map it to a component... eg path === 'Settings. In this example I've just hardwired it in.
this.$navigateTo(Settings);
});
},
render: h => h("frame", [h(Home)]),
store: ccStore
}).$start();

Related

Can a custom vue package export pieces of a Vuex State, that could then be imported/used within a Laravel Project's Vuex State

Hey Stackoverflow community!
I've got a question regarding Vuex in a Laravel/Vue Project, that is also importing a custom Vue components library/package.
I'd like to have our package export certain pieces of Vuex state (state, mutations, getters, etc) that relate specifically to our package.
I'd like these pieces to work with our Laravel Project's Vuex Instance. The hope is that this would allow the project to use state pieces from the custom package, as well as state pieces specific to the Laravel project, in one Vuex Instance.
Is this possible or even a good approach? The package is meant to be re-usable and is not project-specific, but it would be ideal if the Laravel Project could read/manipulate/interact the package state from its own Vuex State.
Here are some relevant code snippets:
Custom Component Library - main.js
import ExampleComponent from './components/ExampleComponent.vue'
import AnotherComponent from './components/AnotherComponent.vue'
export {
ExampleComponent,
AnotherComponent
}
Laravel Project - app.js
import {ExampleComponent, AnotherComponent} from 'vue-components-library'
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
filterData: {
page: 1
},
fetchResultsFlag: 0
},
mutations: {
updateFilterData: (state, filterData) => {
Object.entries(filterData).forEach(([key, value]) => {
state.filterData[key] = value
});
state.fetchResultsFlag = 1
},
incrementPage: (state) => {
state.filterData.page++
state.fetchResultsFlag = 1
},
resetFetchResultsFlag: (state) => {
state.fetchResultsFlag = 0
}
},
getters: {
filterData: state => {
return state.filterData
},
fetchResultsFlag: state => {
return state.fetchResultsFlag
},
page: state => {
return state.filterData.page
}
}
})
const app = new Vue({
el: '#app',
store: store
});
Any help or insight is greatly appreciated!
Thanks.

Vue.component vs import to load a component

Why when I use Vue.component to load the two commented components below, I get the following error in the javascript console while it works with import ?
Uncaught ReferenceError: dashboard is not defined
app.js:
Vue.component('left-menu', require('./components/LeftMenu.vue').default);
// Vue.component('dashboard', require('./components/foo/dashboard.vue').default);
// Vue.component('members', require('./components/foo/members.vue').default);
import dashboard from './components/foo/dashboard.vue';
import members from './components/foo/members.vue';
const routes = [
{
path: '/dashboard',
component: dashboard
},
// {
// path: '/members',
// component: members
// }
];
Because you use dashboard variable in your routes, this variable exists in "import way" but not in "Vue component way"
In the example that generates errors the components are not recognized as variables, so you should do something like :
const dashboard = {
template: `<div>Dashboard</div>` ,
}
const routes = [
{
path: '/dashboard',
component: dashboard
},
// {
// path: '/members',
// component: members
// }
];

How to add loader in vue js

How to add Loading effect in VUE js plus Laravel.
This is a single page website in vuejs, i want to add loader when i change the route.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Means when i click to another router, it takes time to fetch data and show meanwhile i want to show loader. Or When i submit a form i takes time for submit meanwhile i want to add loader.
Help please in VUE js + Laravel
add this line of code in your app.js file
router.beforeEach((to, from, next) => {
// add loader
next()
})
router.afterEach(() => {
// terminate you loader
})
so Full file is
window.Vue = require('vue');
import VueRouter from 'vue-router';
import VueProgressBar from 'vue-progressbar'
window.Fire = new Vue();
Vue.use(VueProgressBar, {
color: 'rgb(143, 255, 199)', //normal color for progress bar
failedColor: 'red', //color for failed progress bar
height: '2px'//height of progress bar can be changed here
})
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
Vue.use(VueRouter);
window.Fire = new Vue();
let routes = [
{
path: '/',
name: 'posts',
component: post,
},
{
path: '/general',
name: 'dashboard',
component: Dashboard,
},
];
let router = new VueRouter({
routes // short for `routes: routes`
});
router.beforeEach((to, from, next) => {
// add loader
VueProgressBar .start();
next()
})
router.afterEach(() => {
// terminate you loader
VueProgressBar.finish();
})
const app = new Vue({
el: '#app',
router,
data: {},
methods: {}
});
window.Fire = new Vue();
If you are requesting while browsing through the pages, the loader can work accordingly.
<script>
export default {
data: () => ({
loaderIsActive: false,
items: null,
}),
mounted() {
this.fetch();
},
methods: {
async fetch() {
this.loaderIsActive = true;
this.items = await axios.post('YOUR API');
this.loaderIsActive = false;
}
}
}
In this way you can use it.

ngOnInit doesn't run until after I navigate to another component

In my NativeScript app, I have the route set up as
export const routes = [
{ path: "", component: AppComponent},
{ path: "home", component: HomeComponent},
{ path: "login", component: LoginComponent},
{ path: "news" , component: NewsComponent}
];
After a user is logged in through firebase the user is auto redirected to the HomeComponent. I should mention that I have a user service that gets fired from the AppComponent Constuctor that determines if a user is already logged in then redirects them to login or home.
I have console.log() spread across the component to see when things gets triggered so I can try to figure out where to place the code.
import {Component, OnInit} from "#angular/core";
import {Page} from "ui/page";
import {RouterExtensions} from 'nativescript-angular/router';
import firebase = require("nativescript-plugin-firebase");
#Component ({
selector : "home",
templateUrl: "./pages/home/home.html",
styleUrls: ["./pages/home/home.css"]
})
export class HomeComponent implements OnInit {
private router;
constructor(page: Page, router: RouterExtensions) {
console.log("HOME CONSTRUCTOR TRIGGERED");
page.actionBarHidden = false;
this.router = router;
}
ngOnInit(){
console.log("HOME NGONIT TRIGGERED");
}
goToNews(){
this.router.navigate(["/news"]);
}
}
In home.html I have a button that triggers goToNews(). When I load up the app, I can see in my console when HomeComponent constructor gets triggered, but I never see ngOnInit get triggered. The strange thing is that when I click on the button to navigate to /news, this is when I see the HomeComponent ngOnInit fire in my console. Is this the way it's suppose to work?
This all comes down to a "big picture understanding" where I'm trying to figure out the best place to put my logic down when HomeComponent gets loaded. I read that putting it in the constructor was a bad idea and having it in ngOnInit is ideal however I don't see how this can make any sense if ngOnInit only gets triggered after I try to navigate away from the component.
Please help me understand this.
UPDATE: I added a console.log to ngOnInit in AppComponent and this does get fired when the app first loads. So it must be the navigation in the services that is causing ngOnInit to not fire in HomeComponent.
Try putting the router.navigate() into a separate "Zone":
import:
import { NgZone } from "#angular/core";
inject:
constructor(private zone: NgZone) { ... }
apply:
this.zone.run(() => {
this.router.navigate(["/news"]);
});
found here.

How do I use vue-resource v-links inside a vueify component?

When using v-link="{ path: '/add' }" in my vueify (used with Laravel) component, I get a v-link can only be used inside a router-enabled app. or a <router-view> can only be used inside a router-enabled app. error.
Here is my main.js: http://laravel.io/bin/Kkj27
My code seems very similar to the example provided for nestedRoutes, I am not sure why this is not working.
This is all a little confusing to me (best practices for structuring Vue.js single page apps) but this is essentially what I did to make it work:
Vue.component('Todo', Todo);
And removing this whole thing:
var TodoApp = new Vue({
el: '#app',
components: { Todo }
});
After this, I can refer to the Todo component in the router.map function.
router.map({
'/': {
component: Todo,
subRoutes: {
'/bar': {
...
},
'/baz': {
...
}
}
}
})

Resources