No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    [solved] When is Dom ready for scroll?

    Help
    1
    2
    1192
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      MusicForMellons last edited by MusicForMellons

      I have multiple children and need to scroll to a certain child after loading the page. I can do so by setting a delay using setTimeout but I would prefer a better/ fail-proof solution. My current approach is to wait for all children to mount (and use nextTick) and thought it should be ready for the scroll, but apparently not. Alternatively I can wait for all images to be loaded (as QImg has a @load event), but that is really late, since manually I can already trigger a scroll while image boxes are already rendered but still loading. What is the best way to trigger at ‘the earliest possible moment’?

      Point-panel (parent):

      new Vue({
        el: '#q-app',
        template: `
            <div id="point-panel" class='map-overlay column scroll'>
                  <small-cards @child-mounted='cardsAreReady' 
                       v-for='(point, cardIndex) in picArray'
                       :key="cardIndex"
                       :point-object="point"
                       :card-index="cardIndex"></small-cards>
                  <q-btn @click.native="scrollToCenter"
                 fab
                 ripple
                 class='fixed'
                 size="10px"
                 color="black"
                 label="scroll"
                 style="right: 18px; bottom: 120px" />
        </div>
              </div>
          `,
        data() {
          return {
            parentMounted: false,
            selectedPointIndex: 6,      
            picArray: ["https://image1", "https://image2, "https://image_etc."]
           }
            },
            mounted: function() {
            let that = this
            	that.$nextTick( function(){
              	that.parentMounted = true
              })
            },
            methods: {
              notify(msg) {
                this.$q.notify(msg)
              },
              cardsAreReady(cardIndex) {
                console.log('one ready.......', `${cardIndex + 1} ...and total ${this.picArray.length}`)
                let that = this
                if (cardIndex + 1 === this.picArray.length) {
                  console.log('....all cards MOUNTED!', cardIndex)
                  setTimeout(() => {
                    that.$nextTick(() => {
                      console.log('..........trigger scroll NOW!')
                      if (that.parentMounted === true) {
                        that.scrollToCenter()
                      } else {
                        that.$q.notify('parent not yet ready!!')
                      }
                    })
                  }, 0)
                }
              },
              scrollToCenter() {
                const that = this
                console.log('..........cardIndex: ', that.selectedPointIndex)
          
          
                function scrollFunction() {
                  that.notify('scroll triggered!')
                  const element = document.getElementsByClassName(
                    that.selectedPointIndex.toString()
                  )
                  const target = document.getElementById('point-panel')
                  const iW = window.innerWidth
                  const iH = window.innerHeight
                  const myOffset = element[0].offsetLeft
                  Quasar.utils.scroll.setHorizontalScrollPosition(target, myOffset, 0)
          
                }
                setTimeout(() => scrollFunction(), 0)
              }
            }
          })
          
      

      Images/ small-cards (children):

      Vue.component('small-cards', {
        props: {
          pointObject: {
            type: Object,
            required: true
          },
          cardIndex: {
            type: Number,
            required: true,
            default: 0
          }
        },
        data() {
          return {
            selectedPointIndex: 6
          }
        },
        mounted: function() {
        let that = this
        that.$nextTick(function () {
         that.$emit('child-mounted', this.cardIndex)
         })
        },
        methods: {
          reportError(event) {
            console.log(`${event.name}: ${event.message}`);
          },
        },
        template: `
              <div class="mycard"
             :class="{'active': cardIndex === selectedPointIndex,
                [cardIndex]: true}">
          <q-img :src="pointObject"
                 spinner-size="30px"
                 style="background-color: rgba(255, 225, 215, 0.4)"
                 @error="reportError">
          </q-img>
        </div>
        `
      })
      

      Here you can find a jsfiddle showing the issue. I have added a scroll button to show that after loading you can trigger a scroll successfully (the 6th picture, i.e. ‘the Tiger’ is scrolled to the bottom-left corner).

      To give the question somewhat more direction: The problem is that if scroll is triggered to soon the Dom is not yet rendered and thus the distance to scrol can not yet be determined. But I would think that after mount in combination with $nextTick the Dom should be determined?! So why does current approach not work?

      1 Reply Last reply Reply Quote 0
      • M
        MusicForMellons last edited by

        After using @load for the scroll-element and adding a nextTick it seems to work as should. See this stackoverflow-issue .

        1 Reply Last reply Reply Quote 0
        • First post
          Last post