ILYASEM
ILYASEM

Reputation: 103

How to automatically scroll only inside <div> tag in Vue.js

I am creating frontend using vue 2.

There I have a chat inside tag and have done auto-scroll to the end of chat on updated().

Unfortunately, it scrolls not only inside chat box but also the whole page to this moment. How to override it? (show the whole code for you to recognise that it's impossible to have a ref on last message but not div - loaded_messages is an array from API and dialogs - from WebSocket)

<template>
          <div class="box col-md-8" >
            <div id="chat-messages" class="chat__order" style=" 
                border: 1px solid grey; overflow-y: scroll;">

                    <ol class="chat">

                  <div v-for="m in loaded_messages[0]"
                        direction="column"
                        justify-content="start"
                        align-items="end"
                        margin-left=2px
                        :key="m.id">
                   <li class="self" v-if="m.username == user"> 
                    <b-avatar :src="m.get_message_info.get_thumbnail"></b-avatar>
                      <div class="msg">

                      <p>{{m.content}} </p>
                      <time>{{m.get_datetime}}</time>

                      </div>
                    </li>

                   <li class="other" v-else> 
                    <b-avatar :src="m.get_message_info.get_thumbnail"></b-avatar>
                        <div class="msg">
                        <p>{{m.content}}</p>
                        <time>{{m.get_datetime}}</time>
                        </div>
                  </li>

                  </div>

                <div  v-for="dialog in dialogs"
                        direction="column"
                        justify-content="start"
                        align-items="end"
                        :key="dialog.id">

                   <li class="self" v-if="dialog.username == user"> 
                    <b-avatar></b-avatar>
                      <div class="msg">
                              <p>{{dialog.message}} </p>
                              <time>{{dialog.datetime}}</time>
                      </div>
                    </li>

                   <li v-else> 
                    <b-avatar></b-avatar>
                    <div class="msg">
                            <p>  {{dialog.message}} </p>
                    </div>
                  </li>

                </div> 

                  <div ref="lastMessage"></div>
              </ol>
          </div>
        </div> 

</template>

<script>

        methods: { 

// scroll to the last message

      scrollToElement() {
      const [el] =  this.$refs.lastMessage;
      if (el) {
        el.scrollIntoView({ behavior: "smooth" });
      }
    },

   },

    updated() {
      this.scrollToElement();
    },

</script>

Upvotes: 1

Views: 914

Answers (1)

Mina
Mina

Reputation: 17594

scrollIntoView method doesn't support scrolling inside a container, it only works with the document viewport, you need to calculate the X distance to the top of the element.

You can use this method.

function scrollParentToChild(parent, child) {
// Where is the parent on page
  var parentRect = parent.getBoundingClientRect();
  // What can you see?
  var parentViewableArea = {
    height: parent.clientHeight,
    width: parent.clientWidth
  };

  // Where is the child
  var childRect = child.getBoundingClientRect();
  // Is the child viewable?
  var isViewable = (childRect.top >= parentRect.top) && (childRect.bottom <= parentRect.top + parentViewableArea.height);

  // if you can't see the child try to scroll parent
  if (!isViewable) {
        // Should we scroll using top or bottom? Find the smaller ABS adjustment
        const scrollTop = childRect.top - parentRect.top;
        const scrollBot = childRect.bottom - parentRect.bottom;
        if (Math.abs(scrollTop) < Math.abs(scrollBot)) {
            // we're near the top of the list
            parent.scrollTop += scrollTop;
        } else {
            // we're near the bottom of the list
            parent.scrollTop += scrollBot;
        }
  }

}

Upvotes: 2

Related Questions