2

I am trying to scroll down on new appeared element in vue:

I have chat messages where I have two arrays:

data() {
  return {
    activeChats: [],
    openedChats: [],
    maxOpened: math.round(window.innerWidth / 300), 
  }
}

When I get new message and the conversation is not in active and opened arrays I add to both and it appears on screen because I used v-for on both arrays.

This everything works but I am not sure how to scroll down on div when new chat appears, I tried using refs but had no luck:

<div class="chat" v-for="chat in openedChats" ref="chat-{chat.id}"></div> Or even just chat testing with one chat opened..

And inside axios then() after success I said:

this.$refs.chat['-'+response.data.id].scrollTo(9999999,99999999);
or
this.$refs.chat['-'+response.data.id].scrollTop = 99999999;
or
this.$refs.chat.scrollTo(9999999,99999999);
or
this.$refs.chat.scrollTop = 99999999;

And neither worked...

Any help ? :D

Can it be done without additional library, I need no animatios just to appear at the bottom of the element...

Thanks

2
  • 1
    There's a handy library for that: rigor789.github.io/vue-scrollto/# Commented Oct 23, 2018 at 14:33
  • Is there a way without additional library? :D Since I dont need smooth scrolling but just appearing at the bottom :D Commented Oct 23, 2018 at 14:34

1 Answer 1

5

See this example:

https://jsfiddle.net/eywraw8t/430100/

Use "watch" (https://v2.vuejs.org/v2/guide/computed.html) to detect changes in the message array (either from ajax or simply a button like in the example). Set the id (or you can use ref if you prefer) based on the index of the message. Then scroll to the last element in your array (get the last one via array.length).

new Vue({
  el: "#app",
  data: {
    messages: [
      { id: 1, text: 'message' },
    ],
  },
  watch:
  {
    messages: function() {
      let id = this.messages.length;
      //takes a bit for dom to actually update
      setTimeout(function() {
          document.getElementById('message-' + id).scrollIntoView();
      }, 100);
      
    },
  },
  methods: {
    addMessage: function(){
      let id = this.messages.length + 1;
      this.messages.push({ id: id, text: 'message'});
    }
  }
})
<div id="app">
  <button v-on:click="addMessage()" style="position:fixed">
  Add message
  </button>
  <div class="message" v-for="message in messages" :id="'message-' + message.id">
    {{message.text}} {{ message.id}}
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

I did it on little different way :D I had two problems, my ref or id were as string, not passing as values so they were undefined. Second problem is that scroll start after array update but there is not element rendered yet so I added settimeout with 100ms and now it works. Btw I am using document.getelementbyid('chat-'+reponse.data.id) as el, and so I say el.scrollTop = el.scrollHeight; inside timeout

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.