Scroll behaviour VueJS not working properly
I am trying to make a scrolling to anchor by means of scrollBehaviour in VueJS.
Generally, I change current router with the following way :
this.$router.push({path : 'componentName', name: 'componentName', hash: "#" + this.jumpToSearchField})
My VueRouter is defined as :
const router = new VueRouter({
routes: routes,
base: '/base/',
mode: 'history',
scrollBehavior: function(to, from, savedPosition) {
let position = {}
if (to.hash) {
position = {
selector : to.hash
};
} else {
position = {x : 0 , y : 0}
}
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(position)
}, 10)
})
}
});
My routes :
[
{
path: '/settings/:settingsId',
component: Settings,
children: [
{
path: '',
name: 'general',
components: {
default: General,
summary: Summary
}
},
{
path: 'tab1',
name: 'tab1',
components: {
default: tab1,
summary: Summary
}
},
{
path: 'tab2',
name: 'tab2',
components: {
default: tab2,
summary: Summary
}
},
{
path: 'tab3',
name: 'tab3',
components: {
default: tab3,
summary: Summary
}
}
]
},
{
path: '/*',
component: Invalid
}
];
Let's say I am on tab1 component and I would like to jump to anchor 'test' on tab3 component
After router.push()
I see that scrollBehavior
is trigged and component switches from tab1 to tab3 as well as URL is changed (e.g. http://localhost:8080/tab1 to http://localhost:8080/tab3#test) but windows location is not placed where anchor is but just on the top of the window.
And of course, I have textarea with id="test" on tab3 component
What can be wrong ?
Solution 1:
Use {left: 0, top: 0}
instead of {x: 0, y: 0}
and it will work.
I think it's a mistake in Vue documentation because if you log savedPosition
on the console, you'll see {left: 0, top: 0}
and when you change {x: 0, y: 0}
like that everything will work perfectly.
Solution 2:
I couldn't get any of the other solutions around this working, and it was really frustrating.
What ended up working for me was the below:
const router = new Router({
mode: 'history',
routes: [...],
scrollBehavior() {
document.getElementById('app').scrollIntoView();
}
})
I mount my VueJs app to #app so i can be certain it is present its available for selection.
Solution 3:
this works for me in Vue 3 :
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
scrollBehavior(to, from, SavedPosition) {
if (to.hash) {
const el = window.location.href.split("#")[1];
if (el.length) {
document.getElementById(el).scrollIntoView({ behavior: "smooth" });
}
} else if (SavedPosition) {
return SavedPosition;
} else {
document.getElementById("app").scrollIntoView({ behavior: "smooth" });
}
},
});