Search code examples
javascriptdomvuejs3vue-composition-apivue-script-setup

How to scrollIntoView in vue composition api that use script setup?


I have a parent app(parent.vue) that emit value from child app(MainMenu.vue) that used to scroll in spesific pageview by id in parent app, but when i run it give the error message TypeError: document.getElementById(...) is null.

This is the parent app that i want to scroll in spesific pageview

parent.vue

<template>
  <section>
    <MainCover></MainCover>
    <QuotePage></QuotePage>
    <GroomBride id='1'></GroomBride>
    <TimeLines id='2'></TimeLines>
    <RunDown id='3'></RunDown>
    <SpecialInvitation></SpecialInvitation>
    <LiveStream></LiveStream>
    <OurMoment id='4'></OurMoment>
    <MessageBox id='5'></MessageBox>
    <FooterPage></FooterPage>
    <MainMenu @coba="onCoba" @page="navigation"></MainMenu>
  </section>
</template>

<script setup>
import QuotePage from '@/components/QuotePage.vue'
import MainCover from '@/components/MainCover.vue'
import GroomBride from '@/components/GroomBride.vue'
import TimeLines from '@/components/TimeLines.vue'
import RunDown from '@/components/RunDown.vue'
import SpecialInvitation from '@/components/SpecialInvitation.vue'
import OurMoment from '@/components/OurMoment.vue'
import MessageBox from '@/components/MessageBox.vue'
import FooterPage from '@/components/FooterPage.vue'
import MainMenu from '@/components/MainMenu.vue'
import LiveStream from '@/components/LiveStream.vue'


// Navigation handler
const navigation = val => {
  console.log(val);
  document.getElementById(val).scrollIntoView({
    behavior: 'smooth'
  })
}

</script>

This is the child app that i emit a value to parent,

MainMenu.vue

<template>
  <div class="container">
      <div class="notification is-primary p-2">
              <!-- <span class="mr-4" @click="editEvent(day.id, event.details)"><fa :icon="['fas', 'pencil']" /></span>
              <span @click="deleteEvent(day.id, event.details)"><fa :icon="['fas', 'trash']" /></span> -->
          <span class="icon-text is-paddingless is-marginless">
              <span @click="navPage('1')" class="icon">
                  <font-awesome-icon icon="fa-solid fa-heart" />
              </span>
              <!-- <span>Couple</span> -->
              <span @click="navPage('2')" class="icon">
                  <font-awesome-icon icon="fa-solid fa-calendar-days" />
              </span>
              <!-- <span>Date</span> -->
              <span @click="navPage('3')" class="icon">
                  <font-awesome-icon icon="fa-solid fa-map" />
              </span>
              <!-- <span>Location</span> -->
              <span @click="navPage('4')" class="icon">
                  <font-awesome-icon icon="fa-solid fa-images" />
              </span>
              <!-- <span>Galleries</span> -->
              <span @click="navPage('5')" class="icon">
                  <font-awesome-icon icon="fa-solid fa-pen-to-square" />
              </span>
              <!-- <span>Wishes</span> -->
          </span>
      </div>
  </div>
</template>

<script setup>
import { defineEmits } from "vue";

const emit = defineEmits(['page']);


const navPage = (value) => {
    emit("page", value)
}

</script>

I consider that the error is in the accessing dom from script setup. I have tried but did'nt get solution, please help. Thanks


Solution

  • Its done, i update my code

    MainMenu.vue

    <template>
      <div class="container">
          <div class="notification is-primary p-2">
              <span class="icon-text is-paddingless is-marginless">
                  <span @click="navPage('groom')" class="icon">
                      <font-awesome-icon icon="fa-solid fa-heart" />
                  </span>
                  <!-- <span>Couple</span> -->
                  <span @click="navPage('time')" class="icon">
                      <font-awesome-icon icon="fa-solid fa-calendar-days" />
                  </span>
                  <!-- <span>Date</span> -->
                  <span @click="navPage('run')" class="icon">
                      <font-awesome-icon icon="fa-solid fa-map" />
                  </span>
                  <!-- <span>Location</span> -->
                  <span @click="navPage('moment')" class="icon">
                      <font-awesome-icon icon="fa-solid fa-images" />
                  </span>
                  <!-- <span>Galleries</span> -->
                  <span @click="navPage('message')" class="icon">
                      <font-awesome-icon icon="fa-solid fa-pen-to-square" />
                  </span>
                  <!-- <span>Wishes</span> -->
              </span>
          </div>
      </div>
    </template>
    
    <script setup>
    import { defineEmits } from "vue";
    
    const emit = defineEmits(['page']);
    
    
    const navPage = (value) => {
        emit("page", value)
    }
    
    </script>
    

    parent.vue

    <template>
      <section>
        <MainCover></MainCover>
        <QuotePage></QuotePage>
        <div ref="groom">
          <GroomBride></GroomBride>
        </div>
        <div ref="time">
          <TimeLines></TimeLines>
        </div>
        <div ref='run'>
          <RunDown></RunDown>
        </div>
        <SpecialInvitation></SpecialInvitation>
        <LiveStream></LiveStream>
        <div ref='moment'>
          <OurMoment></OurMoment>
        </div>
        <div ref='message'>
          <MessageBox></MessageBox>
        </div>
        <FooterPage></FooterPage>
        <MainMenu @page="navigation"></MainMenu>
      </section>
    </template>
    
    <script setup>
    import QuotePage from '@/components/QuotePage.vue'
    import MainCover from '@/components/MainCover.vue'
    import GroomBride from '@/components/GroomBride.vue'
    import TimeLines from '@/components/TimeLines.vue'
    import RunDown from '@/components/RunDown.vue'
    import SpecialInvitation from '@/components/SpecialInvitation.vue'
    import OurMoment from '@/components/OurMoment.vue'
    import MessageBox from '@/components/MessageBox.vue'
    import FooterPage from '@/components/FooterPage.vue'
    import MainMenu from '@/components/MainMenu.vue'
    import LiveStream from '@/components/LiveStream.vue'
    
    import { ref, onMounted } from "vue";
    
    const groom = ref()
    const time = ref()
    const run = ref()
    const moment = ref()
    const message = ref()
    
    
    // // Navigation handler
    const navigation = val => {
      console.log(val)
      if (val == 'groom') {
        groom.value.scrollIntoView({behavior: "smooth"})
      } else if (val == 'time') {
        time.value.scrollIntoView({behavior: "smooth"})
      } else if (val == 'run') {
        run.value.scrollIntoView({behavior: "smooth"})
      } else if (val == 'moment') {
        moment.value.scrollIntoView({behavior: "smooth"})
      } else if (val == 'message') {
        message.value.scrollIntoView({behavior: "smooth"})
      }
    }
    
    
    onMounted( () => {
      navigation();
    })
    
    </script>