Frozen Columns for DataTable

pull/104/head
cagataycivici 2019-11-19 10:51:23 +03:00
parent b50286bca6
commit 2889aeae5b
5 changed files with 138 additions and 9 deletions

View File

@ -23,4 +23,5 @@ export declare class Column extends Vue {
rowReorderIcon?: string; rowReorderIcon?: string;
reorderableColumn?: boolean; reorderableColumn?: boolean;
rowEditor?: boolean; rowEditor?: boolean;
frozen?: boolean;
} }

View File

@ -89,6 +89,10 @@ export default {
rowEditor: { rowEditor: {
type: Boolean, type: Boolean,
default: false default: false
},
frozen: {
type: Boolean,
default: false
} }
}, },
render() { render() {

View File

@ -40,9 +40,9 @@
</table> </table>
</div> </div>
<div class="p-datatable-scrollable-wrapper" v-else> <div class="p-datatable-scrollable-wrapper" v-else>
<DTScrollableView :scrollHeight="scrollHeight" :columns="columns"> <DTScrollableView v-if="hasFrozenColumns" :scrollHeight="scrollHeight" :columns="frozenColumns" :frozenWidth="frozenWidth" :frozen="true">
<template #header> <template #header>
<DTTableHeader :columnGroup="headerColumnGroup" :columns="columns" :rowGroupMode="rowGroupMode" <DTTableHeader :columnGroup="frozenHeaderColumnGroup" :columns="frozenColumns" :rowGroupMode="rowGroupMode"
:groupRowsBy="groupRowsBy" :resizableColumns="resizableColumns" :allRowsSelected="allRowsSelected" :empty="empty" :groupRowsBy="groupRowsBy" :resizableColumns="resizableColumns" :allRowsSelected="allRowsSelected" :empty="empty"
:sortMode="sortMode" :sortField="d_sortField" :sortOrder="d_sortOrder" :multiSortMeta="d_multiSortMeta" :sortMode="sortMode" :sortField="d_sortField" :sortOrder="d_sortOrder" :multiSortMeta="d_multiSortMeta"
@column-click="onColumnHeaderClick($event)" @column-mousedown="onColumnHeaderMouseDown($event)" @column-click="onColumnHeaderClick($event)" @column-mousedown="onColumnHeaderMouseDown($event)"
@ -50,7 +50,7 @@
@column-resizestart="onColumnResizeStart($event)" @checkbox-change="toggleRowsWithCheckbox($event)" /> @column-resizestart="onColumnResizeStart($event)" @checkbox-change="toggleRowsWithCheckbox($event)" />
</template> </template>
<template #body> <template #body>
<DTTableBody :value="dataToRender" :columns="columns" :empty="empty" :dataKey="dataKey" :selection="selection" :selectionKeys="d_selectionKeys" :selectionMode="selectionMode" <DTTableBody :value="dataToRender" :columns="frozenColumns" :empty="empty" :dataKey="dataKey" :selection="selection" :selectionKeys="d_selectionKeys" :selectionMode="selectionMode"
:rowGroupMode="rowGroupMode" :groupRowsBy="groupRowsBy" :expandableRowGroups="expandableRowGroups" :rowClass="rowClass" :editMode="editMode" :compareSelectionBy="compareSelectionBy" :rowGroupMode="rowGroupMode" :groupRowsBy="groupRowsBy" :expandableRowGroups="expandableRowGroups" :rowClass="rowClass" :editMode="editMode" :compareSelectionBy="compareSelectionBy"
:expandedRowIcon="expandedRowIcon" :collapsedRowIcon="collapsedRowIcon" :expandedRows="expandedRows" :expandedRowKeys="d_expandedRowKeys" :expandedRowGroups="expandedRowGroups" :expandedRowIcon="expandedRowIcon" :collapsedRowIcon="collapsedRowIcon" :expandedRows="expandedRows" :expandedRowKeys="d_expandedRowKeys" :expandedRowGroups="expandedRowGroups"
:editingRows="editingRows" :editingRowKeys="d_editingRowKeys" :templates="$scopedSlots" :editingRows="editingRows" :editingRowKeys="d_editingRowKeys" :templates="$scopedSlots"
@ -61,7 +61,7 @@
@row-edit-init="onRowEditInit($event)" @row-edit-save="onRowEditSave($event)" @row-edit-cancel="onRowEditCancel($event)"/> @row-edit-init="onRowEditInit($event)" @row-edit-save="onRowEditSave($event)" @row-edit-cancel="onRowEditCancel($event)"/>
</template> </template>
<template #frozenbody> <template #frozenbody>
<DTTableBody :value="frozenValue" :columns="columns" :dataKey="dataKey" :selection="selection" :selectionKeys="d_selectionKeys" :selectionMode="selectionMode" <DTTableBody :value="frozenValue" :columns="frozenColumns" :dataKey="dataKey" :selection="selection" :selectionKeys="d_selectionKeys" :selectionMode="selectionMode"
:rowGroupMode="rowGroupMode" :groupRowsBy="groupRowsBy" :expandableRowGroups="expandableRowGroups" :rowClass="rowClass" :editMode="editMode" :compareSelectionBy="compareSelectionBy" :rowGroupMode="rowGroupMode" :groupRowsBy="groupRowsBy" :expandableRowGroups="expandableRowGroups" :rowClass="rowClass" :editMode="editMode" :compareSelectionBy="compareSelectionBy"
:expandedRowIcon="expandedRowIcon" :collapsedRowIcon="collapsedRowIcon" :expandedRows="expandedRows" :expandedRowKeys="d_expandedRowKeys" :expandedRowGroups="expandedRowGroups" :expandedRowIcon="expandedRowIcon" :collapsedRowIcon="collapsedRowIcon" :expandedRows="expandedRows" :expandedRowKeys="d_expandedRowKeys" :expandedRowGroups="expandedRowGroups"
:editingRows="editingRows" :editingRowKeys="d_editingRowKeys" :templates="$scopedSlots" :editingRows="editingRows" :editingRowKeys="d_editingRowKeys" :templates="$scopedSlots"
@ -72,7 +72,42 @@
@row-edit-init="onRowEditInit($event)" @row-edit-save="onRowEditSave($event)" @row-edit-cancel="onRowEditCancel($event)"/> @row-edit-init="onRowEditInit($event)" @row-edit-save="onRowEditSave($event)" @row-edit-cancel="onRowEditCancel($event)"/>
</template> </template>
<template #footer> <template #footer>
<DTTableFooter :columnGroup="footerColumnGroup" :columns="columns" /> <DTTableFooter :columnGroup="frozenFooterColumnGroup" :columns="frozenColumns" />
</template>
</DTScrollableView>
<DTScrollableView :scrollHeight="scrollHeight" :columns="scrollableColumns" :frozenWidth="frozenWidth">
<template #header>
<DTTableHeader :columnGroup="headerColumnGroup" :columns="scrollableColumns" :rowGroupMode="rowGroupMode"
:groupRowsBy="groupRowsBy" :resizableColumns="resizableColumns" :allRowsSelected="allRowsSelected" :empty="empty"
:sortMode="sortMode" :sortField="d_sortField" :sortOrder="d_sortOrder" :multiSortMeta="d_multiSortMeta"
@column-click="onColumnHeaderClick($event)" @column-mousedown="onColumnHeaderMouseDown($event)"
@column-dragstart="onColumnHeaderDragStart($event)" @column-dragover="onColumnHeaderDragOver($event)" @column-dragleave="onColumnHeaderDragLeave($event)" @column-drop="onColumnHeaderDrop($event)"
@column-resizestart="onColumnResizeStart($event)" @checkbox-change="toggleRowsWithCheckbox($event)" />
</template>
<template #body>
<DTTableBody :value="dataToRender" :columns="scrollableColumns" :empty="empty" :dataKey="dataKey" :selection="selection" :selectionKeys="d_selectionKeys" :selectionMode="selectionMode"
:rowGroupMode="rowGroupMode" :groupRowsBy="groupRowsBy" :expandableRowGroups="expandableRowGroups" :rowClass="rowClass" :editMode="editMode" :compareSelectionBy="compareSelectionBy"
:expandedRowIcon="expandedRowIcon" :collapsedRowIcon="collapsedRowIcon" :expandedRows="expandedRows" :expandedRowKeys="d_expandedRowKeys" :expandedRowGroups="expandedRowGroups"
:editingRows="editingRows" :editingRowKeys="d_editingRowKeys" :templates="$scopedSlots"
@rowgroup-toggle="toggleRowGroup" @row-click="onRowClick($event)" @row-touchend="onRowTouchEnd" @row-keydown="onRowKeyDown"
@row-mousedown="onRowMouseDown" @row-dragstart="onRowDragStart($event)" @row-dragover="onRowDragOver($event)" @row-dragleave="onRowDragLeave($event)" @row-dragend="onRowDragEnd($event)" @row-drop="onRowDrop($event)"
@row-toggle="toggleRow($event)" @radio-change="toggleRowWithRadio($event)" @checkbox-change="toggleRowWithCheckbox($event)"
@cell-edit-init="onCellEditInit($event)" @cell-edit-complete="onCellEditComplete($event)" @cell-edit-cancel="onCellEditCancel($event)"
@row-edit-init="onRowEditInit($event)" @row-edit-save="onRowEditSave($event)" @row-edit-cancel="onRowEditCancel($event)"/>
</template>
<template #frozenbody>
<DTTableBody :value="frozenValue" :columns="scrollableColumns" :dataKey="dataKey" :selection="selection" :selectionKeys="d_selectionKeys" :selectionMode="selectionMode"
:rowGroupMode="rowGroupMode" :groupRowsBy="groupRowsBy" :expandableRowGroups="expandableRowGroups" :rowClass="rowClass" :editMode="editMode" :compareSelectionBy="compareSelectionBy"
:expandedRowIcon="expandedRowIcon" :collapsedRowIcon="collapsedRowIcon" :expandedRows="expandedRows" :expandedRowKeys="d_expandedRowKeys" :expandedRowGroups="expandedRowGroups"
:editingRows="editingRows" :editingRowKeys="d_editingRowKeys" :templates="$scopedSlots"
@rowgroup-toggle="toggleRowGroup" @row-click="onRowClick($event)" @row-touchend="onRowTouchEnd" @row-keydown="onRowKeyDown"
@row-mousedown="onRowMouseDown" @row-dragstart="onRowDragStart($event)" @row-dragover="onRowDragOver($event)" @row-dragleave="onRowDragLeave($event)" @row-dragend="onRowDragEnd($event)" @row-drop="onRowDrop($event)"
@row-toggle="toggleRow($event)" @radio-change="toggleRowWithRadio($event)" @checkbox-change="toggleRowWithCheckbox($event)"
@cell-edit-init="onCellEditInit($event)" @cell-edit-complete="onCellEditComplete($event)" @cell-edit-cancel="onCellEditCancel($event)"
@row-edit-init="onRowEditInit($event)" @row-edit-save="onRowEditSave($event)" @row-edit-cancel="onRowEditCancel($event)"/>
</template>
<template #footer>
<DTTableFooter :columnGroup="footerColumnGroup" :columns="scrollableColumns" />
</template> </template>
</DTScrollableView> </DTScrollableView>
</div> </div>
@ -294,6 +329,10 @@ export default {
type: Array, type: Array,
default: null default: null
}, },
frozenWidth: {
type: String,
default: null
}
}, },
data() { data() {
return { return {
@ -1485,6 +1524,33 @@ export default {
} }
return columns; return columns;
}, },
frozenColumns() {
let frozenColumns = [];
for(let col of this.columns) {
if(col.frozen) {
frozenColumns = frozenColumns||[];
frozenColumns.push(col);
}
}
return frozenColumns;
},
scrollableColumns() {
let scrollableColumns = [];
for(let col of this.columns) {
if(!col.frozen) {
scrollableColumns = scrollableColumns||[];
scrollableColumns.push(col);
}
}
return scrollableColumns;
},
hasFrozenColumns() {
return this.frozenColumns.length > 0;
},
headerColumnGroup() { headerColumnGroup() {
if (this.allChildren) { if (this.allChildren) {
for (let child of this.allChildren) { for (let child of this.allChildren) {
@ -1496,6 +1562,17 @@ export default {
return null; return null;
}, },
frozenHeaderColumnGroup() {
if (this.allChildren) {
for (let child of this.allChildren) {
if (child.$vnode.tag.indexOf('columngroup') !== -1 && child.type === 'frozenheader') {
return child;
}
}
}
return null;
},
footerColumnGroup() { footerColumnGroup() {
if (this.allChildren) { if (this.allChildren) {
for (let child of this.allChildren) { for (let child of this.allChildren) {
@ -1507,6 +1584,17 @@ export default {
return null; return null;
}, },
frozenFooterColumnGroup() {
if (this.allChildren) {
for (let child of this.allChildren) {
if (child.$vnode.tag.indexOf('columngroup') !== -1 && child.type === 'frozenfooter') {
return child;
}
}
}
return null;
},
processedData() { processedData() {
if (this.lazy) { if (this.lazy) {
return this.value; return this.value;

View File

@ -1,5 +1,5 @@
<template> <template>
<div :class="containerClass"> <div :class="containerClass" :style="containerStyle">
<div class="p-datatable-scrollable-header" ref="scrollHeader" @scroll="onHeaderScroll"> <div class="p-datatable-scrollable-header" ref="scrollHeader" @scroll="onHeaderScroll">
<div class="p-datatable-scrollable-header-box" ref="scrollHeaderBox"> <div class="p-datatable-scrollable-header-box" ref="scrollHeaderBox">
<table class="p-datatable-scrollable-header-table'"> <table class="p-datatable-scrollable-header-table'">
@ -72,18 +72,18 @@ export default {
this.$refs.scrollHeader.scrollLeft = 0; this.$refs.scrollHeader.scrollLeft = 0;
}, },
onBodyScroll() { onBodyScroll() {
let frozenView = this.$refs.previousElementSibling; let frozenView = this.$el.previousElementSibling;
let frozenScrollBody; let frozenScrollBody;
if (frozenView) { if (frozenView) {
frozenScrollBody = DomHandler.findSingle(frozenView, '.p-datatable-scrollable-body'); frozenScrollBody = DomHandler.findSingle(frozenView, '.p-datatable-scrollable-body');
} }
this.$refs.scrollHeaderBox.style.marginLeft = -1 * this.$refs.scrollBody.scrollLeft + 'px'; this.$refs.scrollHeaderBox.style.marginLeft = -1 * this.$refs.scrollBody.scrollLeft + 'px';
if( this.$refs.scrollFooterBox) { if (this.$refs.scrollFooterBox) {
this.$refs.scrollFooterBox.style.marginLeft = -1 * this.$refs.scrollBody.scrollLeft + 'px'; this.$refs.scrollFooterBox.style.marginLeft = -1 * this.$refs.scrollBody.scrollLeft + 'px';
} }
if(frozenScrollBody) { if (frozenScrollBody) {
frozenScrollBody.scrollTop = this.$refs.scrollBody.scrollTop; frozenScrollBody.scrollTop = this.$refs.scrollBody.scrollTop;
} }
/* /*
@ -166,6 +166,24 @@ export default {
computed: { computed: {
containerClass() { containerClass() {
return ['p-datatable-scrollable-view', {'p-datatable-frozen-view': this.frozen, 'p-datatable-unfrozen-view': !this.frozen && this.frozenWidth}]; return ['p-datatable-scrollable-view', {'p-datatable-frozen-view': this.frozen, 'p-datatable-unfrozen-view': !this.frozen && this.frozenWidth}];
},
containerStyle() {
if (this.frozenWidth) {
if (this.frozen) {
return {
width: this.frozenWidth
};
}
else {
return {
width: 'calc(100% - ' + this.frozenWidth + ')',
left: this.frozenWidth
}
}
}
else {
return null;
}
} }
} }
} }

View File

@ -37,6 +37,24 @@
<Column field="brand" header="Brand"></Column> <Column field="brand" header="Brand"></Column>
<Column field="color" header="Color"></Column> <Column field="color" header="Color"></Column>
</DataTable> </DataTable>
<h3>Frozen Columns</h3>
<DataTable :value="cars" :scrollable="true" scrollHeight="200px" frozenWidth="300px">
<Column field="vin" header="Vin" headerStyle="width: 300px" columnKey="vin_1" :frozen="true">
<template #body="slotProps">
<span style="font-weight: bold">{{slotProps.data.vin}}</span>
</template>
</Column>
<Column field="year" header="Year" headerStyle="width: 300px" columnKey="year_1"></Column>
<Column field="brand" header="Brand" headerStyle="width: 300px" columnKey="brand_1"></Column>
<Column field="color" header="Color" headerStyle="width: 300px" columnKey="color_1"></Column>
<Column field="year" header="Year" headerStyle="width: 300px" columnKey="year_2"></Column>
<Column field="brand" header="Brand" headerStyle="width: 300px" columnKey="brand_2"></Column>
<Column field="color" header="Color" headerStyle="width: 300px" columnKey="color_2"></Column>
<Column field="year" header="Year" headerStyle="width: 300px" columnKey="year_3"></Column>
<Column field="brand" header="Brand" headerStyle="width: 300px" columnKey="brand_3"></Column>
<Column field="color" header="Color" headerStyle="width: 300px" columnKey="color_3"></Column>
</DataTable>
</div> </div>
<div class="content-section documentation"> <div class="content-section documentation">