1

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>

1 Answer 1

2

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;
        }
  }

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

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.