Resizable columns for TreeTable

pull/41/head
cagataycivici 2019-08-07 19:40:29 +03:00
parent b469494713
commit 5ad5e7e41e
7 changed files with 188 additions and 32 deletions

View File

@ -943,7 +943,7 @@ export default {
'p-datatable-hoverable-rows': (this.rowHover || this.selectionMode), 'p-datatable-hoverable-rows': (this.rowHover || this.selectionMode),
'p-datatable-auto-layout': this.autoLayout, 'p-datatable-auto-layout': this.autoLayout,
'p-datatable-resizable': this.resizableColumns, 'p-datatable-resizable': this.resizableColumns,
'p-datatable-resizable-fit': this.resizableColumns && this.columnResizeMode === 'fit', 'p-datatable-resizable-fit': this.resizableColumns && this.columnResizeMode === 'fit'
} }
]; ];
}, },

View File

@ -19,11 +19,12 @@
<slot name="paginatorRight"></slot> <slot name="paginatorRight"></slot>
</template> </template>
</TTPaginator> </TTPaginator>
<div class="p-treetable-wrapper"> <div class="p-treetable-tablewrapper">
<table> <table ref="table">
<thead class="p-treetable-thead"> <thead class="p-treetable-thead">
<tr> <tr>
<th v-for="(col,i) of columns" :key="col.columnKey||col.field||i" :style="col.headerStyle" :class="getColumnHeaderClass(col)" @click="onColumnHeaderClick($event, col)"> <th v-for="(col,i) of columns" :key="col.columnKey||col.field||i" :style="col.headerStyle" :class="getColumnHeaderClass(col)" @click="onColumnHeaderClick($event, col)">
<span class="p-column-resizer p-clickable" @mousedown="onColumnResizeStart" v-if="resizableColumns"></span>
<TTColumnSlot :column="col" type="header" v-if="col.$scopedSlots.header" /> <TTColumnSlot :column="col" type="header" v-if="col.$scopedSlots.header" />
<span class="p-column-title" v-if="col.header">{{col.header}}</span> <span class="p-column-title" v-if="col.header">{{col.header}}</span>
<span v-if="col.sortable" :class="getSortableColumnIcon(col)"></span> <span v-if="col.sortable" :class="getSortableColumnIcon(col)"></span>
@ -65,6 +66,7 @@
<div class="p-treetable-footer" v-if="$scopedSlots.footer"> <div class="p-treetable-footer" v-if="$scopedSlots.footer">
<slot name="footer"></slot> <slot name="footer"></slot>
</div> </div>
<div ref="resizeHelper" class="p-column-resizer-helper p-highlight" style="display: none"></div>
</div> </div>
</template> </template>
@ -185,8 +187,20 @@ export default {
filterMode: { filterMode: {
type: String, type: String,
default: 'lenient' default: 'lenient'
},
resizableColumns: {
type: Boolean,
default: false
},
columnResizeMode: {
type: String,
default: 'fit'
} }
}, },
documentColumnResizeListener: null,
documentColumnResizeEndListener: null,
lastResizeHelperX: null,
resizeColumnElement: null,
data() { data() {
return { return {
allChildren: null, allChildren: null,
@ -341,6 +355,7 @@ export default {
return [column.headerClass, return [column.headerClass,
{'p-sortable-column': column.sortable}, {'p-sortable-column': column.sortable},
{'p-resizable-column': this.resizableColumns},
{'p-highlight': sorted} {'p-highlight': sorted}
]; ];
}, },
@ -604,13 +619,97 @@ export default {
}, },
isNodeLeaf(node) { isNodeLeaf(node) {
return node.leaf === false ? false : !(node.children && node.children.length); return node.leaf === false ? false : !(node.children && node.children.length);
},
onColumnResizeStart(event) {
let containerLeft = DomHandler.getOffset(this.$el).left;
this.resizeColumnElement = event.target.parentElement;
this.columnResizing = true;
this.lastResizeHelperX = (event.pageX - containerLeft + this.$el.scrollLeft);
this.bindColumnResizeEvents();
},
onColumnResize(event) {
let containerLeft = DomHandler.getOffset(this.$el).left;
DomHandler.addClass(this.$el, 'p-unselectable-text');
this.$refs.resizeHelper.style.height = this.$el.offsetHeight + 'px';
this.$refs.resizeHelper.style.top = 0 + 'px';
this.$refs.resizeHelper.style.left = (event.pageX - containerLeft + this.$el.scrollLeft) + 'px';
this.$refs.resizeHelper.style.display = 'block';
},
onColumnResizeEnd() {
let delta = this.$refs.resizeHelper.offsetLeft - this.lastResizeHelperX;
let columnWidth = this.resizeColumnElement.offsetWidth;
let newColumnWidth = columnWidth + delta;
let minWidth = this.resizeColumnElement.style.minWidth||15;
if(columnWidth + delta > parseInt(minWidth, 10)) {
if(this.columnResizeMode === 'fit') {
let nextColumn = this.resizeColumnElement.nextElementSibling;
let nextColumnWidth = nextColumn.offsetWidth - delta;
if(newColumnWidth > 15 && nextColumnWidth > 15) {
this.resizeColumnElement.style.width = newColumnWidth + 'px';
if(nextColumn) {
nextColumn.style.width = nextColumnWidth + 'px';
}
}
}
else if(this.columnResizeMode === 'expand') {
this.$refs.table.style.width = this.$refs.table.offsetWidth + delta + 'px';
this.resizeColumnElement.style.width = newColumnWidth + 'px';
}
this.$emit('column-resize-end', {
element: this.resizeColumnElement,
delta: delta
});
}
this.$refs.resizeHelper.style.display = 'none';
this.resizeColumn = null;
DomHandler.removeClass(this.$el, 'p-unselectable-text');
this.unbindColumnResizeEvents();
},
bindColumnResizeEvents() {
if (!this.documentColumnResizeListener) {
this.documentColumnResizeListener = document.addEventListener('mousemove', (event) => {
if(this.columnResizing) {
this.onColumnResize(event);
}
});
}
if (!this.documentColumnResizeEndListener) {
this.documentColumnResizeEndListener = document.addEventListener('mouseup', (event) => {
if(this.columnResizing) {
this.columnResizing = false;
this.onColumnResizeEnd();
}
});
}
},
unbindColumnResizeEvents() {
if (this.documentColumnResizeListener) {
document.removeEventListener('document', this.documentColumnResizeListener);
this.documentColumnResizeListener = null;
}
if (this.documentColumnResizeEndListener) {
document.removeEventListener('document', this.documentColumnResizeEndListener);
this.documentColumnResizeEndListener = null;
}
} }
}, },
computed: { computed: {
containerClass() { containerClass() {
return ['p-treetable p-component', { return ['p-treetable p-component', {
'p-treetable-hoverable-rows': (this.rowHover || this.rowSelectionMode), 'p-treetable-hoverable-rows': (this.rowHover || this.rowSelectionMode),
'p-treetable-auto-layout': this.autoLayout 'p-treetable-auto-layout': this.autoLayout,
'p-treetable-resizable': this.resizableColumns,
'p-treetable-resizable-fit': this.resizableColumns && this.columnResizeMode === 'fit',
}]; }];
}, },
columns() { columns() {

View File

@ -430,6 +430,11 @@ export default new Router({
path: '/treetable/responsive', path: '/treetable/responsive',
name: 'treetableresponsive', name: 'treetableresponsive',
component: () => import('./views/treetable/TreeTableResponsiveDemo.vue') component: () => import('./views/treetable/TreeTableResponsiveDemo.vue')
},
{
path: '/treetable/colresize',
name: 'treetablecolresize',
component: () => import('./views/treetable/TreeTableColResizeDemo.vue')
}, },
{ {
path: '/tristatecheckbox', path: '/tristatecheckbox',

View File

@ -6,25 +6,25 @@
<div class="feature-intro"> <div class="feature-intro">
<h1>DataTable - Column Resize</h1> <h1>DataTable - Column Resize</h1>
<p>Columns can be resized using drag drop by setting the resizableColumns to true. There are two resize modes; "fit" and "expand". Fit is the default one and the overall table width does not change when a column is resized. <p>Columns can be resized using drag drop by setting the resizableColumns to true. There are two resize modes; "fit" and "expand". Fit is the default one and the overall table width does not change when a column is resized.
In "expand" mode, table width also changes along with the column width. onColumnResize is a callback that passes the resized column header as a parameter.</p> In "expand" mode, table width also changes along with the column width.</p>
</div> </div>
</div> </div>
<div class="content-section implementation"> <div class="content-section implementation">
<h3>Fit Mode</h3> <h3>Fit Mode</h3>
<DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit"> <DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit">
<Column field="vin" header="Vin" :resizable="true"></Column> <Column field="vin" header="Vin"></Column>
<Column field="year" header="Year" :resizable="true"></Column> <Column field="year" header="Year"></Column>
<Column field="brand" header="Brand" :resizable="true"></Column> <Column field="brand" header="Brand"></Column>
<Column field="color" header="Color" :resizable="true"></Column> <Column field="color" header="Color"></Column>
</DataTable> </DataTable>
<h3>Expand Mode</h3> <h3>Expand Mode</h3>
<DataTable :value="cars" :resizableColumns="true" columnResizeMode="expand"> <DataTable :value="cars" :resizableColumns="true" columnResizeMode="expand">
<Column field="vin" header="Vin" :resizable="true"></Column> <Column field="vin" header="Vin"></Column>
<Column field="year" header="Year" :resizable="true"></Column> <Column field="year" header="Year"></Column>
<Column field="brand" header="Brand" :resizable="true"></Column> <Column field="brand" header="Brand"></Column>
<Column field="color" header="Color" :resizable="true"></Column> <Column field="color" header="Color"></Column>
</DataTable> </DataTable>
</div> </div>
@ -35,18 +35,18 @@
<template v-pre> <template v-pre>
&lt;h3&gt;Fit Mode&lt;/h3&gt; &lt;h3&gt;Fit Mode&lt;/h3&gt;
&lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit"&gt; &lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit"&gt;
&lt;Column field="vin" header="Vin" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="year" header="Year"&gt;&lt;/Column&gt;
&lt;Column field="brand" header="Brand" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="brand" header="Brand"&gt;&lt;/Column&gt;
&lt;Column field="color" header="Color" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="color" header="Color"&gt;&lt;/Column&gt;
&lt;/DataTable&gt; &lt;/DataTable&gt;
&lt;h3&gt;Expand Mode&lt;/h3&gt; &lt;h3&gt;Expand Mode&lt;/h3&gt;
&lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="expand"&gt; &lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="expand"&gt;
&lt;Column field="vin" header="Vin" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="year" header="Year"&gt;&lt;/Column&gt;
&lt;Column field="brand" header="Brand" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="brand" header="Brand"&gt;&lt;/Column&gt;
&lt;Column field="color" header="Color" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="color" header="Color"&gt;&lt;/Column&gt;
&lt;/DataTable&gt; &lt;/DataTable&gt;
</template> </template>
</CodeHighlight> </CodeHighlight>

View File

@ -540,10 +540,10 @@ data() {
<CodeHighlight> <CodeHighlight>
<template v-pre> <template v-pre>
&lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit | expand"&gt; &lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit | expand"&gt;
&lt;Column field="vin" header="Vin" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="year" header="Year"&gt;&lt;/Column&gt;
&lt;Column field="brand" header="Brand" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="brand" header="Brand"&gt;&lt;/Column&gt;
&lt;Column field="color" header="Color" :resizable="true"&gt;&lt;/Column&gt; &lt;Column field="color" header="Color"&gt;&lt;/Column&gt;
&lt;/DataTable&gt; &lt;/DataTable&gt;
</template> </template>
</CodeHighlight> </CodeHighlight>
@ -552,10 +552,10 @@ data() {
<CodeHighlight> <CodeHighlight>
<template v-pre> <template v-pre>
&lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit | expand"&gt; &lt;DataTable :value="cars" :resizableColumns="true" columnResizeMode="fit | expand"&gt;
&lt;Column field="vin" header="Vin" :resizable="true" headerStyle="width: 20%"&gt;&lt;/Column&gt; &lt;Column field="vin" header="Vin" headerStyle="width: 20%"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year" :resizable="true" headerStyle="width: 40%"&gt;&lt;/Column&gt; &lt;Column field="year" header="Year" headerStyle="width: 40%"&gt;&lt;/Column&gt;
&lt;Column field="brand" header="Brand" :resizable="true" headerStyle="width: 20%"&gt;&lt;/Column&gt; &lt;Column field="brand" header="Brand" headerStyle="width: 20%"&gt;&lt;/Column&gt;
&lt;Column field="color" header="Color" :resizable="true" headerStyle="width: 20%"&gt;&lt;/Column&gt; &lt;Column field="color" header="Color" headerStyle="width: 20%"&gt;&lt;/Column&gt;
&lt;/DataTable&gt; &lt;/DataTable&gt;
</template> </template>
</CodeHighlight> </CodeHighlight>

View File

@ -0,0 +1,52 @@
<template>
<div>
<TreeTableSubMenu />
<div class="content-section introduction">
<div class="feature-intro">
<h1>TreeTable - Column Resize</h1>
<p>Columns can be resized using drag drop by setting the resizableColumns to true. There are two resize modes; "fit" and "expand". Fit is the default one and the overall table width does not change when a column is resized.
In "expand" mode, table width also changes along with the column width.</p>
</div>
</div>
<div class="content-section implementation">
<h3>Fit Mode</h3>
<TreeTable :value="nodes" :resizableColumns="true" columnResizeMode="fit">
<Column field="name" header="Name" :expander="true"></Column>
<Column field="size" header="Size"></Column>
<Column field="type" header="Type"></Column>
</TreeTable>
<h3>Expand Mdoe</h3>
<TreeTable :value="nodes" :resizableColumns="true" columnResizeMode="expand">
<Column field="name" header="Name" :expander="true"></Column>
<Column field="size" header="Size"></Column>
<Column field="type" header="Type"></Column>
</TreeTable>
</div>
</div>
</template>
<script>
import NodeService from '../../service/NodeService';
import TreeTableSubMenu from './TreeTableSubMenu';
export default {
data() {
return {
nodes: null
}
},
nodeService: null,
created() {
this.nodeService = new NodeService();
},
mounted() {
this.nodeService.getTreeTableNodes().then(data => this.nodes = data);
},
components: {
'TreeTableSubMenu': TreeTableSubMenu
}
}
</script>

View File

@ -9,7 +9,7 @@
<li><router-link to="/treetable/selection">&#9679; Selection</router-link></li> <li><router-link to="/treetable/selection">&#9679; Selection</router-link></li>
<li><router-link to="/treetable/lazy">&#9679; Lazy</router-link></li> <li><router-link to="/treetable/lazy">&#9679; Lazy</router-link></li>
<li><router-link to="/treetable/coltoggle">&#9679; ColToggle</router-link></li> <li><router-link to="/treetable/coltoggle">&#9679; ColToggle</router-link></li>
<li><router-link to="/treetable/resize">&#9679; Resize</router-link></li> <li><router-link to="/treetable/colresize">&#9679; Resize</router-link></li>
<li><router-link to="/treetable/responsive">&#9679; Responsive</router-link></li> <li><router-link to="/treetable/responsive">&#9679; Responsive</router-link></li>
</ul> </ul>
</div> </div>