Simple infinite scrolling implementation used on MeetTheAdvocates component (#1099)

This commit is contained in:
korgan00 2020-11-12 11:02:18 +01:00 committed by Salvador de la Puente González
parent 4cb06880f2
commit 8277dcea42
3 changed files with 70 additions and 7 deletions

View File

@ -24,11 +24,14 @@
<AppMultiSelect v-bind="filter" />
</template>
<template slot="results">
<AdvocateCard
v-for="advocate in advocates"
:key="`advocate-${advocate.attributes.name}`"
v-bind="advocate.attributes"
/>
<InfiniteScroll
v-slot="advocate"
:items="advocates"
:min-items="5"
:key-generator="(advocate) => advocate.attributes.name"
>
<AdvocateCard v-bind="advocate.attributes" />
</InfiniteScroll>
</template>
</AppFiltersResultsLayout>
</div>
@ -42,6 +45,7 @@ import AppMultiSelect from '~/components/ui/AppMultiSelect.vue'
import AppFieldset from '~/components/ui/AppFieldset.vue'
import AppCheckbox from '~/components/ui/AppCheckbox.vue'
import AppFiltersResultsLayout from '~/components/ui/AppFiltersResultsLayout.vue'
import InfiniteScroll from '~/components/ui/InfiniteScroll.vue'
@Component({
components: {
@ -49,7 +53,8 @@ import AppFiltersResultsLayout from '~/components/ui/AppFiltersResultsLayout.vue
AppMultiSelect,
AppFieldset,
AppCheckbox,
AppFiltersResultsLayout
AppFiltersResultsLayout,
InfiniteScroll
}
})
export default class extends Vue {

View File

@ -0,0 +1,42 @@
<template>
<div>
<div
v-for="(item, index) in items.slice(0, lastShown)"
:id="index + '-' + keyGenerator(item)"
:key="keyGenerator(item)"
class="scrollable"
>
<slot v-bind="item" />
</div>
</div>
</template>
<script lang="ts">
import { Component, Mixins, Prop } from 'vue-property-decorator'
import ScrollSectionsMixin from '~/mixins/scrollBetweenSections'
@Component
export default class extends Mixins(ScrollSectionsMixin) {
@Prop(Array) items!: Array<any>
@Prop(Function) keyGenerator!: Function
@Prop({ type: Number, default: 5 }) minItems!: number
lastShown: number = Math.min(this.minItems, this.items.length)
/**
* This methods gets called when the active section changes.
* Inherited from ScrollSectionsMixin
*/
activeSectionChanged () : void {
const current: number = this.activeSection ? parseInt(this.activeSection.split('-', 2)[0]) : 0
const oldLastShown = this.lastShown
this.lastShown = Math.max(Math.min(current + this.minItems, this.items.length), this.lastShown)
if (oldLastShown < this.lastShown) {
this.updateObserved()
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -24,6 +24,14 @@ export default class ScrollBetweenSections extends Vue {
})
}
updateObserved () {
(this.$el as HTMLElement)
.querySelectorAll('.scrollable')
.forEach((section) => {
(this._observer as IntersectionObserver).observe(section)
})
}
beforeDestroy () {
this._observer && this._observer.disconnect()
}
@ -50,12 +58,20 @@ export default class ScrollBetweenSections extends Vue {
const triggerWindowBottom = rootBounds.bottom
const onTop = targetTop >= 0 && targetTop <= triggerWindowBottom
if (onTop && targetTop < highestTopValue) {
this.activeSection = target.id
if (this.activeSection !== target.id) {
this.activeSection = target.id
this.activeSectionChanged()
}
highestTopValue = targetTop
}
})
}
/**
* This methods gets called when the active section changes.
*/
activeSectionChanged () {}
_parseSectionFromUrl (route: any) {
this.activeSection = route.hash.substr(1)
}