Two way fixed scrollable table
Vue powered table with fixed column width
by leonsaysHi
HTML
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<div id="table">
<div class="flex-table">
<!-- header -->
<div class="flex-table__header">
<div class="-fixed">
<div v-for="cell in tableDatas.header.fixedcols" v-html="cell.label" class="cell"></div>
</div>
<div class="-scrolled" ref="hcells">
<div v-for="cell in tableDatas.header.cols" v-html="cell.label" class="cell"></div>
</div>
</div>
<!-- body -->
<div class="flex-table__rows" ref="rows">
<div v-for="row in tableDatas.rows" class="flex-table__row">
<div class="-fixed">
<div v-for="cell in row.fixedcols" v-html="cell.label" class="cell"></div>
</div>
<div class="-scrolled">
<div v-for="cell in row.cols" v-html="cell.label" class="cell"></div>
</div>
</div>
</div>
</div>
</div>
SCSS
.flex-table {
$fixed-w: 300px;
$scrolled-w: 200px;
margin: 1rem;
overflow: hidden;
&,
* {
box-sizing: border-box;
}
&__header {
display: flex;
background-color: #ccc;
.-scrolled {
flex-grow: 1;
}
}
&__rows {
height: 200px;
overflow: auto;
}
&__row {
display: flex;
}
.-scrolled,
.-fixed {
position: relative;
display: flex;
}
.-fixed {
position: relative;
z-index: 2;
flex: 0 0 $fixed-w;
background-color: #ccc;
}
.-scrolled .cell {
flex: 0 0 $scrolled-w;
}
.-fixed .cell {
flex: 1 0 0;
}
.cell {
padding: .5em .5em;
}
}
Vue
new Vue({
el: "#table",
data: {
table: {
header: [
{ label: 'col1', fixed: true },
{ label: 'col2', fixed: true },
{ label: 'col3', fixed: true },
{ label: 'col4' },
{ label: 'col5' },
{ label: 'col6' },
{ label: 'col7' },
{ label: 'col8' }
],
rows: [
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}],
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}],
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}],
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}],
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}],
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}],
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}],
[{label: '1'}, {label: '2'}, {label: '3'}, {label: '4'}, {label: '5'}, {label: '6'}]
]
}
},
computed: {
tableDatas: function() {
const obj = {
header:{
fixedcols: this.table.header.filter(i => i.fixed),
cols: this.table.header.filter(i => !i.fixed)
},
rows: this.table.rows.map(r => {
const _r = {
fixedcols: [],
cols: []
}
this.table.header.every((c, idx) => {
const cell = r[idx] || { label: '-' }
if (c.fixed) {
_r.fixedcols.push(cell)
}
else {
_r.cols.push(cell)
}
return true
})
return _r
})
}
console.log(obj)
return obj
}
},
mounted: function() {
const
$tbody = $(this.$refs.rows),
$tbody_cells = $tbody.find('.-fixed'),
$thead_cells = $(this.$refs.hcells)
$tbody.scroll(function(e) {
...