How to scroll to element in v-if with VueJS?

3.8k Views Asked by At

In my Vue 3 project, I have this button in a component:

<template>
  <button type="button" class="btn btn-success" :data-id="product.id"
    v-on:click="hideButtonAndScroll(product.id)">Get Offer</button>

  <!-- ... some code here ... -->

  <offer-form :product="product"></offer-form>
</template>

<script>
export default {
  props: ['products'],
  data() {
    return { visibleFormId: 0 };
  },
  methods: {
    hideButtonAndScroll(id) {
      this.visibleFormId = id;
      window.scrollTo({
        top: document.getElementById('product-id-' + id).offsetTop,
        left: 0,
        behavior: 'smooth',
      });
    }
  },
}
</script>

In the OfferForm.vue file, I have this HTML code:

<template>
  <div :id="'product-id-' + product.id">
    <!-- ... -->
  </div>
</template>

The problem is when I call the document.getElementById('product-id-' + id) function, actually the element doesn't exist yet.

Is there any way to wait until the rendering has finished? and then start scrolling?

1

There are 1 best solutions below

0
tony19 On

You can wait until the next render cycle with await this.$nextTick() to see any side effects from changing visibleFormId (using async/await below):

export default {
  methods: {
  async hideButtonAndScroll(id) {
      this.visibleFormId = id;

    await this.$nextTick();

      window.scrollTo({
        top: document.getElementById('product-id-' + id).offsetTop,
        left: 0,
        behavior: "smooth",
      });
    },
  },
}

demo