'How to combine the vertical scroll of two vuetify data tables?
I have been trying so many different solutions to this problem and have not come close. Any help would be greatly appreciated. I am trying to combine the vertical scroll of three datatables so that if you scroll on any of them they all scroll vertically.
var scrollers = document.getElementsByClassName("scroll-together");
var scrollersTo = Array.from(scrollers);
scrollersTo.find(function (element){
return element.childNodes[1];
})
console.log("scrollersTo", scrollersTo)
var scrollerDivs = Array.prototype.filter.call(
scrollers,
function (testElement) {
return testElement.nodeName === "DIV";
},
console.log("scroller", scrollers),
console.log("scroller divs", scrollerDivs)
);
scrollerDivs.forEach(function (element) {
element.addEventListener("scroll", function (e) {
scrollAll(e.target.scrollTop, scrollerDivs);
});
});
in mounted - above I was trying to access the element and which worked, but it seems like I need to navigate further down in the element into a childNode and nodeName (two different methods) of index 1. This however never would only ever return undefined no matter which method I used.
scrollAll(scrollTop, scrollerDivs) {
scrollerDivs.forEach(function (element) {
console.log("scrollALL", scrollTop);
element.scrollTop = scrollTop;
});
}
Above is the function that should invoke the scrolling in methods
<template>
<v-data-table
:headers="headersSelected"
:items="items"
hide-default-footer
fixed-header
id="optionChainTable"
v-scroll#optionChainTable="scrollOptionChain"
:items-per-page="listLength"
v-sortable-table="{ onEnd: sortTheHeadersAndUpdateTheKey }"
:key="anIncreasingNumber"
item-key="key"
disable-sort
disable-filtering
disable-pagination
class="scroll-together"
>
<!-- v-scroll.self="onScroll" -->
<!-- :loading="isLoading"
-->
<template v-slot:top>
<v-toolbar flat dense>
<template v-if="header == 'Call'">
<v-tooltip right>
<template v-slot:activator="{ on, attrs }">
<v-btn
v-bind="attrs"
v-on="on"
icon
text
small
@click.stop="headersSelectorDialog = true"
>
<v-icon>mdi-table-headers-eye</v-icon>
</v-btn>
</template>
<span class="tooltip">Select Headers</span>
</v-tooltip>
<v-dialog
v-model="headersSelectorDialog"
scrollable
max-width="250px"
>
<v-card>
<v-system-bar color="primary darken-2" dark>
<span class="text-caption">Select Headers</span>
<v-spacer></v-spacer>
<v-icon @click="headersSelectorDialog = false">
mdi-close
</v-icon>
</v-system-bar>
<v-card-text style="height: 400px">
<v-checkbox
dense
v-for="header in headersList"
:key="header.value"
:label="header.text"
hide-details
v-model="header.selectable"
@click="selectHeader(header)"
></v-checkbox>
</v-card-text>
</v-card>
</v-dialog>
</template>
<v-spacer></v-spacer>
<v-toolbar-title>{{ header }}</v-toolbar-title>
<v-spacer></v-spacer>
<template v-if="header == 'Put'">
<v-tooltip right>
<template v-slot:activator="{ on, attrs }">
<v-btn
v-bind="attrs"
v-on="on"
icon
text
small
@click.stop="headersSelectorDialog = true"
>
<v-icon>mdi-table-headers-eye</v-icon>
</v-btn>
</template>
<span class="tooltip">Select Headers</span>
</v-tooltip>
<v-dialog
v-model="headersSelectorDialog"
scrollable
max-width="250px"
>
<v-card>
<v-system-bar color="primary darken-2" dark>
<span class="text-caption">Select Headers</span>
<v-spacer></v-spacer>
<v-icon @click="headersSelectorDialog = false">
mdi-close
</v-icon>
</v-system-bar>
<v-card-text style="height: 400px">
<v-checkbox
dense
v-for="header in headersList"
:key="header.value"
:label="header.text"
hide-details
v-model="header.selectable"
@click="selectHeader(header)"
></v-checkbox>
</v-card-text>
</v-card>
</v-dialog>
</template>
</v-toolbar>
</template>
</v-data-table>
</template>
Solution 1:[1]
You can use the Vuetify v-scroll and target the div/table by using its id, see here scroll target.
Here is the working example, from where you can get the idea. FOR A BETTER VIEW SEE ON FULL SCREEN
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
desserts: [
{ name: 'Frozen Yogurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0, iron: '1%', },
{ name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3, iron: '1%', },
{ name: 'Eclair', calories: 262, fat: 16.0, carbs: 23, protein: 6.0, iron: '7%', },
{ name: 'Cupcake', calories: 305, fat: 3.7, carbs: 67, protein: 4.3, iron: '8%', },
{ name: 'Gingerbread', calories: 356, fat: 16.0, carbs: 49, protein: 3.9, iron: '16%', },
{ name: 'Jelly bean', calories: 375, fat: 0.0, carbs: 94, protein: 0.0, iron: '0%', },
{ name: 'Lollipop', calories: 392, fat: 0.2, carbs: 98, protein: 0, iron: '2%', },
{ name: 'Honeycomb', calories: 408, fat: 3.2, carbs: 87, protein: 6.5, iron: '45%', },
{ name: 'Donut', calories: 452, fat: 25.0, carbs: 51, protein: 4.9, iron: '22%', },
{ name: 'KitKat', calories: 518, fat: 26.0, carbs: 65, protein: 7, iron: '6%', },
],
};
},
methods: {
scrollTable1() {
const table1 = this.$el.querySelector('#table1');
const table2 = this.$el.querySelector('#table2');
table2.scrollTop = table1.scrollTop;
},
scrollTable2() {
const table1 = this.$el.querySelector('#table1');
const table2 = this.$el.querySelector('#table2');
table1.scrollTop = table2.scrollTop;
}
}
});
#table1 {
max-height: 200px;
overflow: auto;
}
#table2 {
max-height: 200px;
overflow: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.24.0/axios.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
<div id="app">
<v-app id="inspire">
<v-row>
<v-col>
<v-data-table
id="table1"
v-scroll:#table1="scrollTable1"
dense :headers="headers"
:items="desserts"
item-key="name"
disable-pagination
hide-default-footer
></v-data-table>
</v-col>
<v-col>
<v-data-table
id="table2"
v-scroll:#table2="scrollTable2"
dense :headers="headers"
:items="desserts"
item-key="name"
disable-pagination
hide-default-footer
></v-data-table>
</v-col>
</v-row>
</v-app>
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Arslan Butt |
