1

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?

tony19
  • 125,647
  • 18
  • 229
  • 307
netdjw
  • 5,419
  • 21
  • 88
  • 162

1 Answers1

3

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

tony19
  • 125,647
  • 18
  • 229
  • 307