Vuetify router not working when called from JavaScript? - vue.js

I am trying to navigate the router from methods in Vuetify, but when putting a /path on the go() function, the whole page just refreshes, and navigates nowhere.
Works:
<v-btn router to="/somepage">Goto page</v-btn>
Doesnt work (page just refreshes):
this.$router.go('/somepage')
Works (history go one step back):
this.$router.go(-1)
Browsing the $router object in the Chrome console, it looks just fine. What am I doing wrong?

Vue router provides several functions for programmatic navigation.
this.$router.go(n)
The go(n) function expects n to be a number and is the number of steps forward or backward in the history to travel. I think this is the reason you're not getting the result you expect.
this.$router.push(path|route)
If you'd like to supply an actual path to the function, you should use push() instead of go(). For example to go to the "home" page you might use this.$router.push('/') or to go to the profile page this.$router.push('/profile'). Importantly, when you use push() the path you submit gets added onto the history stack.
this.$router.replace(path|route)
If you do NOT want to add an entry to the history stack, you should use replace() instead of push(). Otherwise, the usage of replace() is the same as push(), i.e. this.$router.replace('/') or this.$router.replace('/profile').
Using a path vs using a route object
When navigating with push(path|route) and replace(path|route) you have the option to use a path, which is just a string that is the URL of the place you want to go, or using a route object. The route object gives you a lot more control and allows you to send route or query parameters to the destination component.
For example, if you want to navigate to the profile page for the user with an id of 3, you could do something like this.$router.push({ path: '/profile', params: { id: 3 } }). Alternatively, if you're using a named route, you could substitute the route name for the path, i.e. this.$router.push({ name: 'profile', params: { id: 3 } }). The name should correspond to the name assigned to the route wherever you've set up your main Router instance.
Using Vuetify's v-btn component
If you're using a Vuetify button component there is NOT a router attribute. Instead you'd just specify the to attribute and Vuetify should automatically interpret it as if it were a router-link, e.g. <v-btn to="/profile">My Profile</v-btn>. Alternatively, you can use a route object, e.g. <v-btn :to="{ path: '/profile', params: { id: 3 } }">Profile</v-btn>. Importantly, notice the colon (:) preceding the to in the second case. This tells Vue to interpret the attribute value as JavaScript instead of plain text.

Related

(vue router) Is there a neat way to not duplicate code when creating two routes with an almost identical view?

I have a NewArticleView vue component that is mapped to /articles/new, like this:
const routes = [
...
{
path: '/articles/new',
name: 'New Article',
component: NewArticleView
},
...
]
The view is basically just a form.
I want to create an EditArticleView component but it feels wrong making a new component, since it will be almost identical to NewArticleView.
I really wish there was a way to send an edit flag or something when navigating to the route (something like router.push('/articles/new', editArticle=true)), which modifies the behaviour of the component. Like binding form values to the article I want to edit, instead of an empty form, and use an update api call instead of the one used for creating a new article.
Is there a neat way to do this?
You could make one component like ArticleView which accepts a prop named editArticle :
{
path: '/articles/new',
name: 'ArticleView',
component: NewArticleView,
props: route => ({ editArticle: route.query.editArticle})
},
then use it like /articles/new?editArticle=true

How do I pass parameters with router.push in vue.js?

I'm working on a vue.js application. I'm trying to pass parameters in a redirect from one component to another like this:
this.$router.push({
path: '/my-path',
query: {
anArray: [...]
}
});
Once the component at my-path loads, I'm able to retrieve the parameters like this:
const theArray = this.$route.query.anArray;
The problem is that as soon as I refresh the page, the parameters are gone. When I open Chrome DevTools and put a break point where I retrieve the array from $route.query, I see this:
0: "[object Object]"
1: "[object Object]"
2: "[object Object]"
It seems obvious that it's getting this from the url which is:
http://localhost:8080/my-path?anArray=%5Bobject%20Object%5D&anArray=%5Bobject%20Object%5D&anArray=%5Bobject%20Object%5D
It doesn't seem to realize the 'object' terms in the url are just encodings of actual objects, which are available from $route.query the first time it loads.
Is there another way to pass parameters to a component using $router.push() such that the parameters persist on the page even after refreshing?
I could just try:
this.$router.push('/my-path?anArray=[...]');
...but my goal is to hide the parameters from the user (so don't show them in the url). This is another reason I'm looking for an alternate way of passing parameters (it doesn't even hide them).
I also tried:
this.$router.push({
path: '/my-path',
params: {
anArray: [...]
}
});
...but this made the parameters unavailable in the component (I wonder if this has anything to do with our global router which routes '/my-path' to the MyPath component without specifying parameters; is it wiping out the parameters?).
Thanks.
If you want to hide the parameters from the user, you must not use query. Instead, you should use parameters. Here I let you an example:
//routes.js
path: '/:data',
name: 'Home',
component: () => import('pages/YourPage.vue')
//Passing parameters
this.$router.push({
name: 'Home',
params: { data: yourData}
});
//Receiving parameters in Home component
created() {
console.log('Params: ', this.$route.params);
}
I hope this could be usefull
While params suggested #elC0mpa is a correct answer here are some alternatives depending on the use case:
localStorage/SessionStorage
Save the paramters into localStorage/SessionStorage and retrieve them in the loading sequence of your destination-page as #nachodd pointed out.
⚠ It should be noted that only key value pairs in form of strings are being saved into these storages.
You will need something along the line of
localStorage.setItem(itemKey,JSON.stringify(itemValue)
to set the values and
const itemValue = JSON.parse(localStorage.getItem('itemKey')
to recive it. Also localStorage.removeItem('itemKey') for cleanup.
vuex store
You may want to consider saving your data in the store all together and access it from any vue-component.
The commands needed are this.$store.commit('pathToStore/setterForKey',value) to save something into the store and this.$store.getters[pathToStore/getterForKey'] to receive the items value.
⚠ It should be noted that you need to set up the store accordingly with every state setter/mutation, getter and action. See this documentation.

Vuejs <router-link> same route but different parameter

I have the component: same route but different parameter
<router-link :to="{name: 'menu1-mostrar', params: {atr: var1}}">
Menu1
</router-link>
<router-link :to="{name: 'menu1-mostrar', params: {atr: var2}}">
Menu2
</router-link>
I'm not getting the component to update automatically. I can only update by clicking on another menu item that has the different route.
Note that menu 1 and menu 2 use the same route. When I click menu 1 and then if I want to click menu 2 it does not call the route again. I have to call for example menu 3 that uses different route and then menu 2 I need the route always be called independent if I am already in it.
Because the route is the same, the component does not have to be changed, from a vue-router point of view.
Your component must be reactive to the parameter: Change your component values when the parameter change.
Solution 1: Watch for your parameter change, inside the component.
watch:{
atr(newValue, oldValue){
//handle change, maybe refresh
}
}
Solution 2: Use your parameter inside computed values:
computed:{
myBusinessValue(){
return this.atr + " is the value of the param atr!!!"
}
}
Depending of what happend when the parameter change, you will use sol1 or sol2. You can give more details about that to guide you on one or the other.
You need to watch the attribute through the $route object, like so:
watch: {
'$route.params.atr': {
handler () {
// Do stuff
}
}
},

$f7router shows the correct "currentRoute" but $f7router.currentRoute shows previous route

I'm working on a tab view app with VueJS and Framework7.
I have f7-links that each open a f7-view element (so not actual tab elements). Inside one of these tabs, I would want to do nested navigation using f7-link-item with the link parameter. I am using the same component to render this page but I need to pass data to each link to identify which link was clicked (and to know which content to render).
I am trying to get this data with
created() {
console.log(this.$f7router.currentRoute);
}
But the weird thing is, this shows the previous route (the component that the link was clicked on, not the current component). If I do just
created() {
console.log(this.$f7router);
}
THEN the currentRoute shows the correct one.
For reference, my ordinary tab links are like this:
<f7-toolbar tabbar labels bottom id="toolbar">
<f7-link tab-link="#view-menu" tab-link-active text="Menu"></f7-link>
</f7-toolbar>
<f7-view id="view-menu" main tab tab-active url="/menu/"></f7-view>
And my nested routing links are like this:
<f7-list-item link="/product/0" class="product-link">
Coffee
</f7-list-item>
Routing itself works great, I just don't understand how to pass the prop I want and why the currentRoute parameter isn't working.
Thank you very much!
Try using this.$f7route instead of this.$f7router.currentRoute.
$route or $f7route
(object)
Current route. Contains object with route query, hash, params, path and url
https://framework7.io/docs/router-component.html#component-context

Nested Nuxt page says computed property not defined when navigating to another page

I have nested pages that look like this:
/pages/services/index.vue
/pages/services/service-1.vue
...
The index.vue and service-1.vue pages use two different layouts. The layout for service-1.vue has a computed() function like the below.
computed: {
currentService() {
return this.$store.getters.getServiceByUrl(this.$route.path)
}
When on service-1.vue, if I click a <nuxt-link to='/services'> (or any other page) I get an error saying "_vm.currentService is undefined". At this point, if I try to navigate to another page (or simply refresh the current page) the error goes away and the page renders as expected.
I don't understand why this is happening though. Only /services/service-1.vue is using a layout with that computed property, so why is it even being looked for on any other route?