In the related question you posted, we already have a way to achieve that in plain javascript, so we only need to get the js reference to the dom node we want to scroll.
The ref attribute can be used to declare reference to html elements to make them available in vue's component methods.
Or, if the method in the component is a handler for some UI event, and the target is related to the div you want to scroll in space, you can simply pass in the event object along with your wanted arguments, and do the scroll like scroll(event.target.nextSibling).
As I understand, the desired effect you want is to scroll to the end of a list (or scrollable div) when something happens (e.g.: an item is added to the list). If so, you can scroll to the end of a container element (or even the page it self) using only pure JavaScript and the VueJS selectors.
var container = this.$el.querySelector("#container");
container.scrollTop = container.scrollHeight;
I tried the accepted solution and it didn't work for me. I use the browser debugger and found out the actual height that should be used is the clientHeightBUT you have to put this into the updated() hook for the whole solution to work.
data(){
return {
conversation: [
{
}
]
},
mounted(){
EventBus.$on('msg-ctr--push-msg-in-conversation', textMsg => {
this.conversation.push(textMsg)
// Didn't work doing scroll here
})
},
updated(){ <=== PUT IT HERE !!
var elem = this.$el
elem.scrollTop = elem.clientHeight;
},
Here is a simple example using ref to scroll to the bottom of a div.
/*
Defined somewhere:
var vueContent = new Vue({
el: '#vue-content',
...
*/
var messageDisplay = vueContent.$refs.messageDisplay;
messageDisplay.scrollTop = messageDisplay.scrollHeight;
2022 easy, readable, smooth scrolling ability, & won't hurt your brain... use el.scrollIntoView()
scrollIntoView() has options you can pass it like scrollIntoView({behavior: 'smooth'}) to get smooth scrolling out of the box and does not require any external libraries.
methods: {
scrollToElement() {
const el = this.$refs.scrollToMe;
if (el) {
// Use el.scrollIntoView() to instantly scroll to the element
el.scrollIntoView({behavior: 'smooth'});
}
}
}
Then if you wanted to scroll to this element on page load you could call this method like this:
mounted() {
this.scrollToElement();
}
Else if you wanted to scroll to it on a button click or some other action you could call it the same way:
<button @click="scrollToElement">scroll to me</button>
The scroll works all the way down to IE 8. The smooth scroll effect does not work out of the box in IE or Safari. If needed there is a polyfill available for this here as @mostafaznv mentioned in the comments.
For those that haven't found a working solution above, I believe I have a working one. My specific use case was that I wanted to scroll to the bottom of a specific div - in my case a chatbox - whenever a new message was added to the array.
I have to use nextTick as we need to wait for the dom to update from the data change before doing the scroll!
I just put the above code in a watcher for the messages array, like so:
messages: {
handler() {
// this scrolls the messages to the bottom on loading data
const container = this.$el.querySelector('#messagesCard');
this.$nextTick(() => {
// DOM updated
container.scrollTop = container.scrollHeight;
});
},
deep: true,
},
scrollToElement() {
const element = this.$refs.abc; // here abc is the ref of the element
if (element) {
el.scrollIntoView({behavior: 'smooth'});
}
}
}
here you need to use ref for the particular div or element which you want make visible on scroll.
if you have a table and you want to locate the last row of the table then you have to use -
Here not that if you ware asynchronously adding the element to the table then you have to take care of it. you can test it using setTimeout, if that is making any difference.
e.g.
const element = this.$refs.abc;
if (element) {
setTimeout(() => {
element.lastElementChild.scrollIntoView({behaviour:'smooth'})
}, 1000);
}
}