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

    Infinite Scroller Loses Reactivity when Adding New Data after Initial Loading of Data

    CLI
    3
    10
    1169
    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.
    • C
      carlos_proj last edited by

      I am trying to use quasar infinite-scroll to enhance rendering time with large amounts of data in my website. I am querying data from a sever and sorting that data into tables. The tables are then put into cards. Each card can have up to 100 rows of data with up to 10 columns. Additionally, the card heights are variable and the number of cards are also variable. Finally, users can change information that is fed into the card generation or table information thus I need the infinite scroll to “restart” whenever one of these variables change.

      So far I have a “working” state of the infinite scroll meaning that I see that not all the data is loaded at once. The part I need help on is the reactivity portion. The content of the web page does not refresh whenever one of the variables are updated from the user side. Please let me know if these things don’t make sense

      I should add that I the website was reactive when the cards weren’t wrapped around the q-infinite-scroll component. I just took a huge hit on rendering time since everything was trying to be loaded at once.

      I am also open to suggestions on other methods of enhancing rendering

      <q-infinite-scroll
            class="col-12 justify-center"
            :handler="loadMore"
            :offset="40"
          >
            <div class="row col-12 shadow-1 q-mt-md q-pa-lg results-card"
              v-for="(item, index) in items" :key="index"
              ref="collate"
            >
              <!-- check title -->
              <div
                v-if="searchText"
                class="col-12 text-weight-light uppercase"
                v-html="highlight(item)"
              />
              <div v-else
                class="col-12 text-weight-light uppercase"
              >
                {{item.target}}
              </div>
              <!-- collation table -->
              <results-collate-table
                dense
                class="col-12 no-shadow"
                :visibleColumns="[...currentColumnPreset.selections, ...nonCommonColumnNames]"
                :items="orderItems(rolledItems.map[item.target])"
              />
            </div>
            <q-spinner-dots
              class="offset-sm-6"
              color="primary"
              :size="40"
              v-if="!turnOff">
            </q-spinner-dots>
          </q-infinite-scroll>
      
      
      methods: {
      loadMore (index, done) {
            // If there is more than 1 dispo loaded, then add a delay to the rendering
            if (this.selectedPendingItems.length + this.selectedApprovedItems.length === 1) {
              this.delay = 0
            }
            // Mechanism for loading more violations
            if (this.turnOff === false) {
              setTimeout(() => {
                let items = []
                // Load violations in steps of itemLoad
                for (var i = this.idx; i < this.idx + this.itemLoad; i++) {
                  if (i < this.filteredCheckNames.length) {
                    items.push(this.filteredCheckNames[i])
                  } else {
                    this.turnOff = true
                  }
                }
                this.idx = i
                this.items = this.items.concat(items)
                done()
              }, this.delay)
            }
          },
      

      filteredchecknames is an object of strings that are keys to see what data to load
      this is what users choose

      1 Reply Last reply Reply Quote 0
      • s.molinari
        s.molinari last edited by

        Hi Carlos, can you show all the code in the <script> section of the component?

        Scott

        1 Reply Last reply Reply Quote 0
        • C
          carlos_proj last edited by

          <script>
          import { scroll } from 'quasar'
          const { getScrollTarget, setScrollPosition } = scroll
          import ResultsCollateTable from '../components/ResultsCollateTable.vue'
          import { mapState, mapGetters } from 'vuex'
          import fuzzysort from 'fuzzysort'
          
          export default {
            name: 'CollateResultsPage',
            components: {
              ResultsCollateTable
            },
            data () {
              return {
                items: [],
                idx: 0,
                turnOff: false,
                itemLoad: 3,
                delay: 1000
              }
            },
            computed: {
              ...mapState('appCompareDatas', ['searchText']),
              ...mapState('compareDatas', [
                'reviewItems',
                'selectedPendingItems',
                'selectedApprovedItems'
              ]),
              ...mapState('persistCompareDatas', [
                'autoColumns'
              ]),
              ...mapGetters('persistCompareDatas', [
                'currentColumnPreset',
                'currentRowPreset'
              ]),
              ...mapGetters('compareDatas', [
                'fetchItemsLoading',
                'haveReviewItems',
                'rollItems'
              ]),
              allItems () {
                return [
                  ...this.selectedPendingItems,
                  ...this.selectedApprovedItems
                ]
              },
              fieldRecords () {
                const items = this.allItems, fields = this.autoColumns
                const fieldSet = fields.reduce((o, f) => {
                  items.forEach(i => {
                    f.name in o ? o[f.name].add(i[f.name]) : o[f.name] = new Set([i[f.name]])
                  })
                  return o
                }, {})
                return fields.map(f => ({
                  name: f.name,
                  label: f.label,
                  value: Array.from(fieldSet[f.name])
                }))
              },
              commonTags () {
                return this.fieldRecords.filter(r => r.value.length === 1)
                  .map(r => ({...r, value: r.value[0]}))
              },
              nonCommonTags () {
                return this.fieldRecords.filter(r => r.value.length !== 1)
              },
              nonCommonColumnNames () {
                return this.nonCommonTags.map(f => f.name)
              },
              rolledItems () {
                return this.rollItems(this.allItems)
              },
              rolledCheckNames () {
                return this.rolledItems.checks
              },
              filteredRolledCheckNames () {
                let names = [...this.rolledCheckNames]
                if (this.currentRowPreset.value === 'hideZero') {
                  names = names.filter(name => (this.groupVioCount(name) > 0))
                } else if (this.currentRowPreset.value === 'hidePendingZero') {
                  names = names.filter(name => (this.groupPendingVioCount(name) > 0))
                } else if (this.currentRowPreset.value === 'showOnlyZero') {
                  names = names.filter(name => (this.groupVioCount(name) === 0))
                }
                return names
              },
              rolledTargets () {
                return this.filteredRolledCheckNames.map(t => fuzzysort.prepare(t))
              },
              filteredCheckNames () {
                return !this.searchText
                  ? this.filteredRolledCheckNames.map(name => ({target: name}))
                  : fuzzysort.go(this.searchText, this.rolledTargets, {
                    threshold: -10000,
                    allowTypo: true,
                    limit: 200
                  })
              },
              showing () {
                return `${this.filteredCheckNames.length}/${this.rolledCheckNames.length}`
              }
            },
            methods: {
              loadMore (index, done) {
                // If there is more than 1 Data loaded, then add a delay to the rendering
                if (this.selectedPendingItems.length + this.selectedApprovedItems.length === 1) {
                  this.delay = 0
                }
                // Mechanism for loading more violations
                if (this.turnOff === false) {
                  setTimeout(() => {
                    let items = []
                    // Load violations in steps of itemLoad
                    for (var i = this.idx; i < this.idx + this.itemLoad; i++) {
                      if (i < this.filteredCheckNames.length) {
                        items.push(this.filteredCheckNames[i])
                      } else {
                        this.turnOff = true
                      }
                    }
                    this.idx = i
                    this.items = this.items.concat(items)
                    done()
                  }, this.delay)
                }
              },
              orderItems (resultsMap) {
                return this.rolledItems.ids
                  .filter(id => id in resultsMap)
                  .map(id => resultsMap[id])
              },
              highlight (result) {
                return result ? fuzzysort.highlight(result, '<span class="text-primary">', '</span>') : ''
              },
              groupVioCount (groupName) {
                const group = this.rolledItems.map[groupName]
                const oids = Object.keys(group)
                return oids.map(id => group[id])
                  .map(item => item.count)
                  .reduce((a, c) => a + c, 0)
              },
              groupPendingVioCount (groupName) {
                const group = this.rolledItems.map[groupName]
                const oids = Object.keys(group)
                return oids.map(id => group[id])
                  .filter(item => item.scope === 'pending')
                  .map(item => item.count)
                  .reduce((a, c) => a + c, 0)
              },
              detectColumnPreset () {
                const flaggedChecks = !this.searchText
                  ? this.filteredRolledCheckNames.map(name => ({target: name}))
                  : fuzzysort.go(this.searchText, this.rolledTargets, {
                    threshold: -10000,
                    allowTypo: true,
                    limit: 1
                  })
                flaggedChecks[0].target = flaggedChecks[0].target.startsWith('/') ? flaggedChecks[0].target.substring(1) : flaggedChecks[0].target
                const numberElements = flaggedChecks[0].target.split('/')
                return numberElements.length > 1
                  ? 'test1' : 'test2'
              },
              scrollToElement (el) {
                let target = getScrollTarget(el)
                let offset = el.offsetTop - el.scrollHeight
                let duration = 1000
                setScrollPosition(target, offset, duration)
              }
            },
            filters: {
              sanitizedTagValues: v => v.toUpperCase()
            },
            mounted () {
              this.currentColumnPreset.value = this.detectColumnPreset()
            }
          }
          </script>
          
          1 Reply Last reply Reply Quote 0
          • s.molinari
            s.molinari last edited by

            Not sure, but I think it’s the concat of array items. I don’t think that will work.

            https://vuejs.org/v2/guide/list.html#Mutation-Methods

            Scott

            1 Reply Last reply Reply Quote 0
            • C
              carlos_proj last edited by

              I tried using push on this.items instead and I still have the same issue

              1 Reply Last reply Reply Quote 0
              • C
                carlos_proj last edited by

                I know I’ve already asked several times but is there a way to programatically restart the q-infinite-scroll? I was thinking that whenever the user changes one of the variables to just call this function. That way it would just do it properly.

                1 Reply Last reply Reply Quote 0
                • s.molinari
                  s.molinari last edited by

                  That shouldn’t matter. Once the data is reactive, it stays reactive.Try something smaller. Smaller data set smaller everything and see if you can get it going with the thought pattern you have. It will be easier to reason about and in the end, you might find your solution.

                  Scott

                  1 Reply Last reply Reply Quote 0
                  • C
                    carlos_proj last edited by

                    I still have not been able to get this one… I tried on very small sets of data to no avail

                    1 Reply Last reply Reply Quote 0
                    • s.molinari
                      s.molinari last edited by

                      And with the information given, I can’t help much either.

                      Scott

                      1 Reply Last reply Reply Quote 0
                      • Hawkeye64
                        Hawkeye64 last edited by

                        @carlos_proj You might want to check this out: https://vuejs.org/2016/02/06/common-gotchas/

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