151 lines
4.0 KiB
Vue
151 lines
4.0 KiB
Vue
<template>
|
|
<div class="Scroll-Table">
|
|
<my-input :props="{type: 'text', placeholder: 'Suche'}" @change="searchChanged" v-model="currentSearch"></my-input>
|
|
<my-table :actions="actions" :columns="columns" :rows="rows"
|
|
:currentOrderBy="currentOrderBy"
|
|
:currentOrderDesc="currentOrderDesc"
|
|
@sort="sort">
|
|
</my-table>
|
|
<div v-if="loadingDelayed">loading...</div>
|
|
<div style="padding-left: 30%; padding-bottom: 100px;">
|
|
<span v-show="hasMore || reloadTriggered" v-if="!loadingDelayed" v-observe-visibility="visibilityChanged">...</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import MyTable from 'components/my-table';
|
|
import MyInput from 'components/my-input';
|
|
|
|
import { ObserveVisibility } from 'vue-observe-visibility/dist/vue-observe-visibility';
|
|
|
|
export default {
|
|
name: "ScrollTable",
|
|
directives: {
|
|
ObserveVisibility
|
|
},
|
|
components: {
|
|
MyTable,
|
|
MyInput
|
|
},
|
|
props: {
|
|
actions: {
|
|
type: Array,
|
|
default() {
|
|
return [ ];
|
|
}
|
|
},
|
|
columns: {
|
|
type: Array,
|
|
default() {
|
|
return [ ];
|
|
}
|
|
},
|
|
newRows: {
|
|
type: Array,
|
|
default() {
|
|
return [ ];
|
|
}
|
|
},
|
|
offset: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
limit: {
|
|
type: Number,
|
|
default: 10
|
|
},
|
|
orderBy: {
|
|
type: String
|
|
},
|
|
orderDesc: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
search: {
|
|
type: String
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
hasMore: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
handler: {
|
|
type: Function,
|
|
default: () => {}
|
|
}
|
|
},
|
|
watch: {
|
|
newRows(rows) {
|
|
rows.forEach(row => {
|
|
this.rowsToPush.push(row);
|
|
});
|
|
this.currentOffset += rows.length;
|
|
this.pushRows(); // for transition
|
|
},
|
|
loading(l) {
|
|
if (!l) {
|
|
// delay after loading for visibility observer
|
|
setTimeout(() => {
|
|
this.loadingDelayed = false;
|
|
}, 200);
|
|
} else {
|
|
this.loadingDelayed = true;
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
rows: [ ],
|
|
rowsToPush: [ ],
|
|
currentOffset: this.offset,
|
|
currentOrderBy: this.orderBy,
|
|
currentOrderDesc: this.orderDesc,
|
|
currentSearch: this.search,
|
|
loadingDelayed: false,
|
|
reloadTriggered: false
|
|
}
|
|
},
|
|
methods: {
|
|
visibilityChanged(isVisible) {
|
|
if (isVisible) {
|
|
// infinite scrolling
|
|
this.reloadTriggered = false;
|
|
this.handler(this.currentOffset, this.limit, this.currentOrderBy, this.currentOrderDesc, this.currentSearch);
|
|
}
|
|
},
|
|
pushRows() {
|
|
let row = this.rowsToPush.shift();
|
|
if (row) {
|
|
this.rows.push(row);
|
|
setTimeout(() => {
|
|
this.pushRows();
|
|
}, 20);
|
|
}
|
|
},
|
|
clear() {
|
|
this.currentOffset = 0;
|
|
this.rows = [];
|
|
this.rowsToPush = [];
|
|
},
|
|
sort(e) {
|
|
if (e.orderBy == this.currentOrderBy) {
|
|
this.currentOrderDesc = !this.currentOrderDesc;
|
|
} else {
|
|
this.currentOrderDesc = false;
|
|
}
|
|
this.currentOrderBy = e.orderBy;
|
|
this.reloadTriggered = true;
|
|
this.clear();
|
|
},
|
|
searchChanged(e) {
|
|
this.currentSearch = e;
|
|
this.reloadTriggered = true;
|
|
this.clear();
|
|
}
|
|
}
|
|
}
|
|
</script> |