How to use $navigateTo in natviescript-vue vuex store actions? - vue.js

this.$navigateTo works perfectly fine within the methods of my components, but inside a mutation neither of Vue.$navigateTo and this.$navigateTo work. My navigation depends on the result I get from an api call, if there is no way to perform a navigation from within store actions, how can I get some return value from an store action so I can perform my navigation within my component?

You can return a value from a store action. Since actions are async, you will need to handle the resulting promise, doing something like
store.dispatch('actionA').then((target) => {
// navigate to target
})
The concept is explained here:
https://vuex.vuejs.org/guide/actions.html#composing-actions

Here is How I solved it:
new Vue({
store,
render: h => h('frame', [h(store.state.is_logged_in ? App : Login)]),
created() {
this.$store.commit('setNav', t => this.$navigateTo(t));
if (this.$store.state.is_logged_in) {
this.$store.dispatch('init');
}
},
}).$start();
Now in my actions I do:
logout({commit, state}) {
console.log('logged out');
commit('log_out');
state.nav(Login);
},

Related

Is there a way to show a bootstrap-vue $toast feedback in beforeRouteEnter?

I have a component which loads a single user, so I use a vue-router guard to load data and in case of error redirect back to the users list component.
Is there a way to show a vue-bootstrap $toast? Usually I access $toast from this component, but obviously this does not exists yet in beforeRouteEnter.
I know I could manage in other ways (show the error in the page and use created(), or use vuex to keep the error and show it in the next page), but since I am using $toast everywhere I would like to keep consistency.
I have no ideas... if only I could access the root component I would have access to $toast but I can't see a way.
// userComponent
// ...
beforeRouteEnter(to, from, next) {
Promise.all([store.dispatch("users/fetchOne", { id: to.params.id } )])
.then(next)
.catch(() => {
// this.$root.$bvToast.toast("ERROR!!!", { variant: "danger" }); // can't do this :(
next("/users");
});
},
//...
You don't have access to this inside beforeRouteEnter. So you can do below :
next(vm => {
vm.$root.$bvToast.toast(...)
})

In vue.js, where can I place "app initialization" code?

Specifically, code that runs before the app actually loads. I'm using vuex and the first thing I want to do (regardless of what route the user is on) is to dispatch a getUser action to get currently user details from the API (or alternatively, redirect if not authenticated).
If I place it in my App.vue mounted component, I believe it might be too late? Don't children components load before parents?
If I get it right you want to do something before the application initialize. For that you can just perform async method in app initialization. Something like that as an example:
function initializeApp (vueCreated) {
return new Promise((resolve, reject) => {
switch (vueCreated) {
case false: // "prevue" initialization steps
console.log('vue not yet created, prevue steps happens')
// ...
setTimeout(_ => resolve(), 3500) // async call
break;
case true: // we can continue/prepare data for Vue
console.log('vue created, but waiting for next initialization steps and data')
// ...
setTimeout(_ => resolve('Mounted / shown when app ready'), 3500) // async call
}
})
}
initializeApp(false).then(_ => {
new Vue({
template: '#app',
data: {
content: null
},
async created () {
this.content = await initializeApp(true)
this.$mount('#app')
console.log('all inicialization steps done, data arrived, vue mounted')
}
})
})
I have found some article related to your question may be this help you out. Link
If you are using vue-router you can use beforeEach to prevent some routes of unauthenticated users.
You can read more here.
If you get stuck here provide code what you tried with router.
Also good example of using navigation guards.
Good luck!

Nuxt/Vuejs - How to create utils that have access to modules?

I am using asiox/vuejs to create a webpage. However I want to compartmentalize the code more. One example is I use axios to make requests to the backend, and the data in the response is commited into vuex.
this.$axios.get('events').then((response) => {
this.$store.commit('data/populate', response.data)
})
.catch((e) => {
console.error(e)
})
I want to write a util method for this, like this.$populate.events()
I have tried creating utils inside the plugins/ directory, but they dont have access to this.$axios or this.$store
Note that I have axios and vuex imported in nuxt.config.js
How can this be achieved?
If you need the function in the context, Vue instances and maybe even
in the Vuex store, you can use the inject function, which is the
second parameter of the plugins exported function.
Injecting content into Vue instances works similar to when doing this
in standard Vue apps. The $ will be prepended automatically to the
function.
Reference
export default ({ app, store }, inject) => {
inject("populate", () => {
app.$axios
.get("events")
.then(response => {
store.commit("data/populate", response.data);
})
.catch(e => {
console.error(e);
});
});
};
app variable is context property.
The root Vue instance options that includes all your plugins. For
example, when using axios, you can get access to $axios through
context.app.$axios.
Figured it out not 5 minutes after posting ...
Basically use this nuxt guide
And replace this with app in the method you'd like to move

How to watch on Route changes with Nuxt and asyncData

Hi everybody i'm trying to watch on route changes in my nuxt js app.
Here my middleware:
export default function ({ route }) {
return route; but i don't know what to write here
}
index.vue File
middleware: [routeReact]
i'm trying to write this:
app.context.route = route
but it says to me that app.context doesn't exist
Here's the point of my question i'm trying to update my data that gets from my api with axios on page if route changing
like this
this the page
i'm clicking link to next page :
but when i'm route to next page, nothing happens all data is the same:
here my asyncData code:
asyncData({ app }) {
return app.$axios.$get('apps/' + app.context.route.fullPath.replace(/\/categories\/?/, ''))
.then(res => {
return {
info: res.results,
nextPage: res.next,
prevPage: res.prev
};
})
}
Thanks for your help
First thing, context.route or it's alias this.$route is immutable object and should not be assigned a value.
Instead, we should use this.$router and it's methods for programmatic navigation or <nuxt-link> and <router-link>.
As I understand, you need to render the same route, but trigger asyncData hook in order to update component's data. Only route query is changed.
Correct way to navigate to the same page but with different data is to use link of such format:
<nuxt-link :to="{ name: 'index', query: { start: 420 }}"
Then you can use nuxt provided option watchQuery on page component and access that query inside asyncData as follows:
watchQuery: true,
asyncData ({ query, app }) {
const { start } = query
const queryString = start ? `?start=${start}` : ''
return app.$axios.$get(`apps/${queryString}`)
.then(res => {
return {
info: res.results,
nextPage: res.next,
prevPage: res.prev
}
})
},
This option does not require usage of middleware. If you want to stick to using middleware functions, you can add a key to layout or page view that is used. Here is an example of adding a key to default layout:
<nuxt :key="$route.fullPath" />
This will force nuxt to re-render the page, thus calling middlewares and hooks. It is also useful for triggering transitions when switching dynamic routes of the same page component.

Confused with Vuex commit/dispatch in simple VueJS test

From the book:
To invoke a mutation handler, you need to call store.commit with its type: store.commit('increment')
Mutations must always be synchronous.
From the book:
Actions commit mutations ( can be asynchronous )
Actions are triggered with the store.dispatch method: store.dispatch('increment')
So it's action -> mutation -> new state most of the time.
So what's confusing me, is the very simple example, whereby I'm trying to show the asynchronous result of an object getTest
See this pen
Why can't Vue see that I'm not calling a mutation, but an action when the component loads?
What is this "book" you are talking about? I'm asking because you are using a mix of new Vuex 2.* and old, Vuex 1.* syntax, which is not working anymore in 2.*, so I assume you are learning in part from outdated resources.
(Sidenote: Why are you using Vue 1? Vue2.* has been out for over 10 months now...)
Your action and mutation definitions are correct, but there's no vuex: {} key in components anymore in Vuex 2.*
Also, you are trying to dispatch an action 'INCREMENT', but oyour store only has a mutation by that name, no action. So you have to use commit rather than dispatch.
Instead, you directly add computed props and method to your instance, or use the map*helpers provided by Vuex:
var vm = new Vue({
el: '[vue=app]',
data: {
welcome: 'Testing Vuex'
},
store: myStore,
created() {
this.$store.dispatch(FETCH_TEST_STATE)
},
computed: {
...Vuex.mapState( {
count: state => state.count,
getTest: state => state.testState
}),
}
methods: {
increment({dispatch}) {
this.$store.commit('INCREMENT', 1)
}
}
})
the action you call from created doesn't work because async/await was acting up on codepen
the commit called from this action didn't set any state.
Fixing all of this, here's your working example:
https://codepen.io/LinusBorg/pen/NvRYYy?editors=1010