Initiated scrollable treetable
parent
0a52948b4c
commit
8329ed5423
|
@ -469,6 +469,7 @@
|
|||
{
|
||||
"name": "TreeTable",
|
||||
"meta": ["treetable"],
|
||||
"badge": "New",
|
||||
"children": [
|
||||
{
|
||||
"name": "Documentation",
|
||||
|
@ -510,6 +511,11 @@
|
|||
"name": "Resize",
|
||||
"to": "/treetable/colresize"
|
||||
},
|
||||
{
|
||||
"name": "Scroll",
|
||||
"to": "/treetable/scroll",
|
||||
"badge": "New"
|
||||
},
|
||||
{
|
||||
"name": "Responsive",
|
||||
"to": "/treetable/responsive"
|
||||
|
|
|
@ -153,7 +153,7 @@ export default {
|
|||
let right = 0;
|
||||
let next = this.$el.nextElementSibling;
|
||||
if (next) {
|
||||
right = DomHandler.getOuterWidth(next) + parseFloat(next.style.left);
|
||||
right = DomHandler.getOuterWidth(next) + parseFloat(next.style.right);
|
||||
}
|
||||
this.styleObject.right = right + 'px';
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
<slot name="paginatorRight"></slot>
|
||||
</template>
|
||||
</TTPaginator>
|
||||
<div class="p-treetable-wrapper">
|
||||
<div class="p-treetable-wrapper" :style="{maxHeight: scrollHeight}">
|
||||
<table ref="table">
|
||||
<thead class="p-treetable-thead">
|
||||
<tr>
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
|
||||
<th v-if="!columnProp(col, 'hidden')" :style="columnProp(col, 'headerStyle')" :class="getColumnHeaderClass(col)" @click="onColumnHeaderClick($event, col)"
|
||||
<th v-if="!columnProp(col, 'hidden')" :style="[columnProp(col, 'style'),columnProp(col, 'headerStyle')]" :class="getColumnHeaderClass(col)" @click="onColumnHeaderClick($event, col)"
|
||||
:tabindex="columnProp(col, 'sortable') ? '0' : null" :aria-sort="getAriaSort(col)" @keydown="onColumnKeyDown($event, col)">
|
||||
<span class="p-column-resizer" @mousedown="onColumnResizeStart" v-if="resizableColumns"></span>
|
||||
<component :is="col.children.header" :column="col" v-if="col.children && col.children.header" />
|
||||
|
@ -34,22 +34,12 @@
|
|||
</tr>
|
||||
<tr v-if="hasColumnFilter()">
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
|
||||
<th v-if="!columnProp(col, 'hidden')" :class="getFilterColumnHeaderClass(col)" :style="columnProp(col, 'filterHeaderStyle')">
|
||||
<th v-if="!columnProp(col, 'hidden')" :class="getFilterColumnHeaderClass(col)" :style="[columnProp(col, 'style'),columnProp(col, 'filterHeaderStyle')]">
|
||||
<component :is="col.children.filter" :column="col" v-if="col.children && col.children.filter"/>
|
||||
</th>
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot class="p-treetable-tfoot" v-if="hasFooter">
|
||||
<tr>
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
|
||||
<td v-if="!columnProp(col, 'hidden')" :style="columnProp(col, 'footerStyle')" :class="columnProp(col, 'footerClass')">
|
||||
<component :is="col.children.footer" :column="col" v-if="col.children && col.children.footer" />
|
||||
{{columnProp(col, 'footer')}}
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody class="p-treetable-tbody">
|
||||
<template v-if="!empty">
|
||||
<TTRow v-for="node of dataToRender" :key="node.key" :columns="columns" :node="node" :level="0"
|
||||
|
@ -62,6 +52,16 @@
|
|||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot class="p-treetable-tfoot" v-if="hasFooter">
|
||||
<tr>
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
|
||||
<td v-if="!columnProp(col, 'hidden')" :style="[columnProp(col, 'style'),columnProp(col, 'footerStyle')]" :class="getColumnFooterClass(col)">
|
||||
<component :is="col.children.footer" :column="col" v-if="col.children && col.children.footer" />
|
||||
{{columnProp(col, 'footer')}}
|
||||
</td>
|
||||
</template>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<TTPaginator v-if="paginatorBottom" :rows="d_rows" :first="d_first" :totalRecords="totalRecordsLength" :pageLinkSize="pageLinkSize" :template="paginatorTemplate" :rowsPerPageOptions="rowsPerPageOptions"
|
||||
|
@ -222,6 +222,18 @@ export default {
|
|||
showGridlines: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
scrollable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
scrollDirection: {
|
||||
type: String,
|
||||
default: "vertical"
|
||||
},
|
||||
scrollHeight: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
documentColumnResizeListener: null,
|
||||
|
@ -391,14 +403,22 @@ export default {
|
|||
return false;
|
||||
},
|
||||
getColumnHeaderClass(column) {
|
||||
return [this.columnProp(column, 'headerClass'),
|
||||
{'p-sortable-column': this.columnProp(column, 'sortable')},
|
||||
{'p-resizable-column': this.resizableColumns},
|
||||
{'p-highlight': this.isColumnSorted(column)}
|
||||
];
|
||||
return [this.columnProp(column, 'headerClass'), {
|
||||
'p-sortable-column': this.columnProp(column, 'sortable'),
|
||||
'p-resizable-column': this.resizableColumns,
|
||||
'p-highlight': this.isColumnSorted(column),
|
||||
'p-frozen-column': this.columnProp(column, 'frozen')
|
||||
}];
|
||||
},
|
||||
getFilterColumnHeaderClass(column) {
|
||||
return ['p-filter-column', this.columnProp(column, 'filterHeaderClass')];
|
||||
return ['p-filter-column', this.columnProp(column, 'filterHeaderClass'), {
|
||||
'p-frozen-column': this.columnProp(column, 'frozen')
|
||||
}];
|
||||
},
|
||||
getColumnFooterClass(column) {
|
||||
return [this.columnProp(column, 'footerClass'), {
|
||||
'p-frozen-column': this.columnProp(column, 'frozen')
|
||||
}];
|
||||
},
|
||||
getSortableColumnIcon(column) {
|
||||
let sorted = false;
|
||||
|
@ -805,7 +825,12 @@ export default {
|
|||
'p-treetable-auto-layout': this.autoLayout,
|
||||
'p-treetable-resizable': this.resizableColumns,
|
||||
'p-treetable-resizable-fit': this.resizableColumns && this.columnResizeMode === 'fit',
|
||||
'p-treetable-gridlines': this.showGridlines
|
||||
'p-treetable-gridlines': this.showGridlines,
|
||||
'p-treetable-scrollable': this.scrollable,
|
||||
'p-treetable-scrollable-vertical': this.scrollable && this.scrollDirection === 'vertical',
|
||||
'p-treetable-scrollable-horizontal': this.scrollable && this.scrollDirection === 'horizontal',
|
||||
'p-treetable-scrollable-both': this.scrollable && this.scrollDirection === 'both',
|
||||
'p-treetable-flex-scrollable': (this.scrollable && this.scrollHeight === 'flex')
|
||||
}];
|
||||
},
|
||||
columns() {
|
||||
|
@ -1006,4 +1031,75 @@ export default {
|
|||
justify-content: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Scrollable */
|
||||
.p-treetable-scrollable .p-treetable-wrapper {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable .p-treetable-table {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable .p-treetable-thead,
|
||||
.p-treetable-scrollable .p-treetable-tbody,
|
||||
.p-treetable-scrollable .p-treetable-tfoot {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable .p-treetable-thead > tr,
|
||||
.p-treetable-scrollable .p-treetable-tbody > tr,
|
||||
.p-treetable-scrollable .p-treetable-tfoot > tr {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable .p-treetable-thead > tr > th,
|
||||
.p-treetable-scrollable .p-treetable-tbody > tr > td,
|
||||
.p-treetable-scrollable .p-treetable-tfoot > tr > td {
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable .p-treetable-thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable .p-treetable-tfoot {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable .p-frozen-column {
|
||||
position: sticky;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.p-treetable-scrollable-both .p-treetable-thead > tr > th,
|
||||
.p-treetable-scrollable-both .p-treetable-tbody > tr > td,
|
||||
.p-treetable-scrollable-both .p-treetable-tfoot > tr > td,
|
||||
.p-treetable-scrollable-horizontal .p-treetable-thead > tr > th
|
||||
.p-treetable-scrollable-horizontal .p-treetable-tbody > tr > td,
|
||||
.p-treetable-scrollable-horizontal .p-treetable-tfoot > tr > td {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.p-treetable-flex-scrollable {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.p-treetable-flex-scrollable .p-treetable-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<tr :class="containerClass" @click="onClick" @keydown="onKeyDown" @touchend="onTouchEnd" :style="node.style" tabindex="0">
|
||||
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
|
||||
<td v-if="!columnProp(col, 'hidden')" :style="columnProp(col, 'bodyStyle')" :class="columnProp(col, 'bodyClass')">
|
||||
<td v-if="!columnProp(col, 'hidden')" :style="[columnProp(col, 'style'),columnProp(col, 'bodyStyle')]" :class="getColumnBodyClass(col)">
|
||||
<button type="button" class="p-treetable-toggler p-link" @click="toggle" v-if="columnProp(col, 'expander')" :style="togglerStyle" tabindex="-1" v-ripple>
|
||||
<i :class="togglerIcon"></i>
|
||||
</button>
|
||||
|
@ -245,7 +245,12 @@ export default {
|
|||
check: event.check,
|
||||
selectionKeys: _selectionKeys
|
||||
});
|
||||
}
|
||||
},
|
||||
getColumnBodyClass(column) {
|
||||
return [this.columnProp(column, 'bodyClass'), {
|
||||
'p-frozen-column': this.columnProp(column, 'frozen')
|
||||
}];
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
|
|
|
@ -771,6 +771,11 @@ const routes = [
|
|||
name: 'treetablecolresize',
|
||||
component: () => import('../views/treetable/TreeTableColResizeDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/treetable/scroll',
|
||||
name: 'treetablescroll',
|
||||
component: () => import('../views/treetable/TreeTableScrollDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/tristatecheckbox',
|
||||
name: 'tristatecheckbox',
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="content-section introduction">
|
||||
<div class="feature-intro">
|
||||
<h1>TreeTable <span>Scroll</span></h1>
|
||||
<p>Data scrolling is available horizontally, vertically or both with support for frozen columns.</p>
|
||||
</div>
|
||||
<AppDemoActions />
|
||||
</div>
|
||||
|
||||
<div class="content-section implementation">
|
||||
<div class="card">
|
||||
<h5>Vertical</h5>
|
||||
<TreeTable :value="nodes" style="margin-bottom: 2rem" :scrollable="true" scrollHeight="400px">
|
||||
<Column field="name" header="Name" :expander="true" style="min-width:200px"></Column>
|
||||
<Column field="size" header="Size" style="min-width:200px"></Column>
|
||||
<Column field="type" header="Type" style="min-width:200px"></Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5>Flexible Scroll</h5>
|
||||
<p>Flex scroll feature makes the scrollable viewport section dynamic insteaf of a fixed value so that it can grow or shrink relative to the parent size of the table.
|
||||
Click the button below to display a maximizable Dialog where data viewport adjusts itself according to the size changes.</p>
|
||||
|
||||
<Button label="Show" icon="pi pi-external-link" @click="openDialog" />
|
||||
</div>
|
||||
|
||||
<Dialog header="Flex Scroll" v-model:visible="dialogVisible" :style="{width: '75vw'}" :maximizable="true" :modal="true" :contentStyle="{height: '300px'}">
|
||||
<TreeTable :value="nodes" :scrollable="true" scrollHeight="flex">
|
||||
<Column field="name" header="Name" :expander="true" style="min-width:200px"></Column>
|
||||
<Column field="size" header="Size" style="min-width:200px"></Column>
|
||||
<Column field="type" header="Type" style="min-width:200px"></Column>
|
||||
</TreeTable>
|
||||
<template #footer>
|
||||
<Button label="Ok" icon="pi pi-check" @click="closeDialog" />
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<div class="card">
|
||||
<h5>Horizontal and Vertical with Footer</h5>
|
||||
<TreeTable :value="nodes" :scrollable="true" scrollHeight="400px" scrollDirection="both">
|
||||
<Column field="name" header="Name" footer="Name" :expander="true" style="width:300px"></Column>
|
||||
<Column header="Key" footer="Key" style="width:300px">
|
||||
<template #body="{node}">
|
||||
{{node.key}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="size" header="Size" footer="Size" style="width:300px"></Column>
|
||||
<Column field="type" header="Type" footer="Type" style="width:300px"></Column>
|
||||
<Column header="Children" footer="Children" style="width:300px">
|
||||
<template #body="{node}">
|
||||
{{node.children ? node.children.length : 0}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column header="Options" footer="Options" style="width:300px">
|
||||
<template #body>
|
||||
<Button type="Button" icon="pi pi-check" label="Edit" class="p-mr-2"></Button>
|
||||
<Button type="Button" icon="pi pi-check" label="Delete" class="p-button-warning"></Button>
|
||||
</template>
|
||||
</Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5>Frozen Columns</h5>
|
||||
<ToggleButton v-model="optionsFrozen" onIcon="pi pi-lock" offIcon="pi pi-lock-open" onLabel="Unfreeze Options" offLabel="Freeze Options" style="width: 12rem" />
|
||||
|
||||
<TreeTable :value="nodes" :scrollable="true" scrollHeight="400px" scrollDirection="both" class="p-mt-3">
|
||||
<Column field="name" header="Name" :expander="true" style="width:300px" frozen></Column>
|
||||
<Column header="Key" style="width:300px">
|
||||
<template #body="{node}">
|
||||
{{node.key}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="size" header="Size" style="width:300px"></Column>
|
||||
<Column field="type" header="Type" style="width:300px"></Column>
|
||||
<Column header="Children" style="width:300px">
|
||||
<template #body="{node}">
|
||||
{{node.children ? node.children.length : 0}}
|
||||
</template>
|
||||
</Column>
|
||||
<Column header="Options" style="width:200px" alignFrozen="right" :frozen="balanceFrozen">
|
||||
<template #body>
|
||||
<Button type="Button" icon="pi pi-check" label="Edit Item" class="p-mr-2" style="width:100%"></Button>
|
||||
</template>
|
||||
</Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AppDoc name="TreeTableScrollDemo" :sources="sources" :service="['NodeService']" :data="['treetablenodes']" github="treetable/TreeTableSizeDemo.vue" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeService from '../../service/NodeService';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
nodes: null,
|
||||
dialogVisible: false,
|
||||
optionsFrozen: false,
|
||||
sources: {
|
||||
'options-api': {
|
||||
tabName: 'Options API Source',
|
||||
content: `
|
||||
<template>
|
||||
<div>
|
||||
<div class="card">
|
||||
<TreeTable :value="nodes" class="p-treetable-sm" style="margin-bottom: 2rem">
|
||||
<template #header>
|
||||
Small Table
|
||||
</template>
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<TreeTable :value="nodes" style="margin-bottom: 2rem">
|
||||
<template #header>
|
||||
Normal Table
|
||||
</template>
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<TreeTable :value="nodes" class="p-treetable-lg" >
|
||||
<template #header>
|
||||
Large Table
|
||||
</template>
|
||||
<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';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
nodes: null
|
||||
}
|
||||
},
|
||||
nodeService: null,
|
||||
created() {
|
||||
this.nodeService = new NodeService();
|
||||
},
|
||||
mounted() {
|
||||
this.nodeService.getTreeTableNodes().then(data => this.nodes = data);
|
||||
}
|
||||
}
|
||||
<\\/script>
|
||||
`
|
||||
},
|
||||
'composition-api': {
|
||||
tabName: 'Composition API Source',
|
||||
content: `
|
||||
<template>
|
||||
<div>
|
||||
<div class="card">
|
||||
<TreeTable :value="nodes" class="p-treetable-sm" style="margin-bottom: 2rem">
|
||||
<template #header>
|
||||
Small Table
|
||||
</template>
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<TreeTable :value="nodes" style="margin-bottom: 2rem">
|
||||
<template #header>
|
||||
Normal Table
|
||||
</template>
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<TreeTable :value="nodes" class="p-treetable-lg" >
|
||||
<template #header>
|
||||
Large Table
|
||||
</template>
|
||||
<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 { ref, onMounted } from 'vue';
|
||||
import NodeService from './service/NodeService';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
onMounted(() => {
|
||||
nodeService.value.getTreeTableNodes().then(data => nodes.value = data);
|
||||
})
|
||||
|
||||
const nodes = ref();
|
||||
const nodeService = ref(new NodeService());
|
||||
|
||||
return { nodes, nodeService }
|
||||
}
|
||||
}
|
||||
<\\/script>
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
nodeService: null,
|
||||
created() {
|
||||
this.nodeService = new NodeService();
|
||||
},
|
||||
mounted() {
|
||||
this.nodeService.getTreeTableNodes().then(data => this.nodes = data);
|
||||
},
|
||||
methods: {
|
||||
openDialog() {
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
closeDialog() {
|
||||
this.dialogVisible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue