0

I have the following v-for and when i add a new comment I want to scroll to that comment but I'm getting the following error in console:

Cannot read property 'top' of undefined

This is the line causing the error in my add method:

$('html, body').animate({scrollTop: $("#comment-" + response.data.id).offset().top}, 2000);

I've checked console and response.data.id is not empty so it must be to do with jquery not recognising the added element. any ideas?

<ul class="list-inline">
   <li v-for="(comment, index) in comments" 
       :key="comment.id" 
       :id="'comment-' + comment.id">
     <span v-html="comment.comment"></span>
    </li>
</ul>

 var vm =  new Vue({
    el: '#root',
    data: {
       comments: [
                {
                  "id": 2,
                  "comment": "blah...",
                },
                {
                  "id": 4,
                  "comment": "blah...",
                }
                {
                  "id": 6,
                  "comment": "blah...",
                }
        ]
     },
     methods: {
        add: function (comment) {
             axios.post("api/comments/add, { comment: comment })
               .then((response) => {
                  this.comments.push(response.data);
                  $('html, body').animate({scrollTop: $("#comment-" + response.data.id).offset().top}, 2000);

                })
               .catch((error) => {}); 
        }

    }
 });    
3
  • What is the value of response.data.id? My guess is that #comment-X doesn't exist and therefore .offset() returns undefined. Commented Dec 11, 2017 at 15:57
  • @Joe it should exist becuase i call this.comments.push(response.data); before i call the scroll function. response.data.id has the id value of the newly created comment e.g. 8 Commented Dec 11, 2017 at 16:03
  • @user1497119 is correct with their answer, #comment-X doesn't exist yet when you try to scroll to it. Commented Dec 11, 2017 at 16:25

2 Answers 2

3

You might want to wait until its rendered on the page before trying to manipulate the Object with jQuery.

// next line adds it into the shadow dom
this.comments.push(response.data)
// next tick is called after rendering
this.$nextTick(() => {
  $('html, body').animate({scrollTop: $("#comment-" + response.data.id).offset().top}, 2000)
})

Also check out https://v2.vuejs.org/v2/api/#Vue-nextTick

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

Comments

0

You can use vue-scrollto that gives you many options and compatibility, even for Nuxt.js

Given an url like http://localhost:9104/post/477#entry-1327 use a watch and a computed property to assure all data is rendered before scroll to the element.

  watch: {
    render (n) { // computed prop (bool) that tells me when all api data is already loaded
      const hash = location.hash.substr(1)
      if (!hash) return
      if (n) {
        this.$nextTick(() => {
          var el = document.getElementById(hash)
          this.$scrollTo(el)
        })
      }
    }
  },

Special ball

How to build a proper link with a hash

this.$router.push({ name: 'post', params: { postId }, hash: `#entry-${parentId}` })

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.