VueJS goBack from Dynamic Route - vue.js

I have / and /items/:name
I go / then /items/iphone5 then /items/phone6
Then call $router.go(-1) and that direct me to / instead of /items/iphone5
What's wrong?
Update:
beforeRouteUpdate (to, from, next) {
this.toggleSideBar()
next()
}
this code works, but dunno why not adding history,
then I create a promise to solve
beforeRouteUpdate (to, from, next) {
this.toggleSideBar().then(() => next())
}

Maybe you uses replace option on your anchor.
please check out your tag has this property
<router-link :to="..." **replace**>

Then call $router.go(-1) and that direct me to / instead of /items/iphone5
go method is based on history API
go(-1) returns to previous entry stored in the current history entry
I go / then /items/iphone5 then /items/phone6
You have to inspect whether the history entry counts for your route or try using history mode
vue router default mode is hash.
const router = new VueRouter({
mode: 'history',
routes: [...]
})
Read docs for more info [Read caveats in the last and Server Side Rendering in first place if you have some time]

Related

Vue Router - Set default query parameters

I'm implementing an paginated list. Therefore I'm using query parameters like ?size=10. This query paramter needs to be always inside my URL (like /home?size=2).
This apporach is not working:
const routes = [{ path: "/home", query: { size: "10" }, components: MyPage }];
const router = createRouter({
history: createWebHistory(),
routes,
});
I thought it is instantiating the route with some parameters. Looking into the Routing section of vue devtools shows me an empty query object:
$route:/home
fullPath:"/home"
path:"/home
query:Object (empty)
hash:""
name:undefined
params:Object (empty)
matched:Array[0]
meta:Object (empty)
redirectedFrom:undefined
href:"/home
How can I set a default query param to my route?
Here is a proposal using the beforeEach NavigationGuard:
const routes = [{ path: "/home", name: "Home", components: MyPage }];
const router = createRouter({
history: createWebHistory(),
routes,
});
router.beforeEach((to, from) => {
if(to.name === "Home" && !to.query.hasOwnProperty("size")){
to.query.size = "10"
}
})
The idea is to add to the route a default query parameter for size when it is not there.
The only way to achieve this properly without defining the default value in every router.push() is probably with Navigation Gurads. You can use them to get the query-parameters that are currently in the url, add the default query-params you need and then return the new route.
Though I would not do it, this is probably the easiest way to achieve this.
And if you want to make them customizable via pinia/vuex you would need to set up a store and make a user input to change the setting.
Note: Pinia is most likely the better option, because it is newer and will still be supported far in the future

How can I set a default value on router.back() for deep linked items in VueJS

I have two (or more) VueJS routes that contain a router-link pointing to the same third route.
/pages/list
<router-link :to="{name:'add-page'}">Add</router-link>
/pages/other-list
<router-link :to="{name:'add-page'}">Add</router-link>
If I put a put link on the third page with $router.back(), the link will take me back in history to whichever previous page I came from.
However, if enter the add-page route directly into my browser, there is no history. I would like to set a default value for that page, and preferably not rely on a global default.
What is the best way to select a default route if there is no history on a specific component?
Would a Navigation Guard fits your needs?
You would use it something like:
router.beforeEach((to, from, next) => {
if (to.name === 'add-page' && to.) {
//Your logic here
//eg a redirect
next({ name: 'MyBaseRoute' })
} else {
next()
}
})
or if you need just for a selected component you can use the in-component guard:
beforeRouteEnter (to, from, next) {
// called before the route that renders this component is confirmed.
// does NOT have access to `this` component instance,
// because it has not been created yet when this guard is called!
},

Vue: only allow access to page if redirected to programatically

I have a route which shows after a user has completed a payment, say at the /success URL. How would I make that someone can't simply go to example.com/success and see the success screen. Instead, it should only be accessed by running this.$router.go('/success/'); in code.
Thanks
Take a look at Navigation Guards.
You can add a beforeEnter to the route which you can use to check if the user should access the page.
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
You can do this with router navigation guards, in particular in-component guards. By defining the beforeRouteEnter, you can check (for example) the store, to see if data associated with payments is defined.

Navigate with Vue router-link changing only query parameters, not path

In Vue.js, I'm using <router-link> to navigate, as such:
<router-link :to="{ path: '/', query: { q: item.id, lang: lang } }">{{item.name}}</router-link>
This does not update the path, only the query string. Although the resulting URL is formatted correctly, it does not trigger navigation in Vue, apparently because the path has not changed, only the query string.
If I put a beforeRouteUpdate hook on my component, I can see that the new query parameters appear in the "to" object.
How can I make Vue perform the navigation, even though only the query parameters have changed?
You have most probably solved this already, so this answer could be useful for others with this problem.
Documentation link - In-Component Guards - beforeRouteUpdate
If I put a beforeRouteUpdate hook on my component, I can see that the new query parameters appear in the "to" object
This means you doing it all correctly since you are seeing the new parameters in the component guard, So next, what you need to do is to do as prescribed below in docs and example
Fetching After Navigation
So all you now have to do is fetch your new data using these new parameters
beforeRouteUpdate (to, from, next) {
this.post = null
// replace `getItem` with your data fetching util / API wrapper
getItem(to.params.q, to.params.lang, (err, post) => {
this.post = post
next()
})
}

Difference between beforeRouteUpdate and watching '$route' - Vue.js?

As we know, to react to params changes in the same component we use beforeRouteUpdate hook or watching $route.
watching $route:
const User = {
template: '...',
watch: {
'$route' (to, from) {
// react to route changes...
}
}
}
beforeRouteUpdate Method:
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// react to route changes...
next()
}
}
What is the difference between these two? if both are same then why vue router introduced beforeRouteUpdate?
From the documentation on beforeRouteUpdate:
called when the route that renders this component has changed, but this component is reused in the new route. For example, given a route with params /users/:id, when we navigate between /users/1 and /users/2, the same UserDetails component instance will be reused, and this hook will be called when that happens. Because the component is mounted while this happens, the navigation guard has access to this component instance.
The documentation is admittedly unclear that the hook gets called before the value of the $route object actually changes. That's the difference between this navigation hook and setting a watcher on $route, which will get called after the value of $route has changed.
Using the beforeRouteUpdate navigation guard, you can determine whether or not you want to prevent the route from changing (by not calling next()) or go to a different route entirely (by passing a different route value like next('/foo'), next({ name: 'foo' }), etc.).
Here's an example fiddle that shows when these functions get called.
As #thanksd said $route is like guard. With watching you can't prevent the route from taking action, but with beforeRouteUpdate you can do it with next function. for example you can wait untill your data is fetched then proceed to the component.
You can find more information in vue-router documentation Data Fetching.