Single and Multiple Selection for TreeTable
parent
b6e91552bb
commit
0ef6de80a3
|
@ -983,6 +983,10 @@ export default {
|
|||
table-layout: auto;
|
||||
}
|
||||
|
||||
.p-datatable-hoverable-rows .p-datatable-tbody > tr.p-highlight {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
.p-datatable-header,
|
||||
.p-datatable-footer {
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<tbody class="p-treetable-tbody">
|
||||
<template v-if="!empty">
|
||||
<TTRow v-for="node of dataToRender" :key="node.key" :columns="columns" :node="node" :level="0"
|
||||
:expandedKeys="d_expandedKeys" @node-toggle="onNodeToggle"
|
||||
:expandedKeys="d_expandedKeys" @node-toggle="onNodeToggle" @node-click="onNodeClick"
|
||||
:selectionMode="selectionMode" :selectionKeys="selectionKeys"></TTRow>
|
||||
</template>
|
||||
<tr v-else class="p-treetable-emptymessage">
|
||||
|
@ -231,6 +231,85 @@ export default {
|
|||
this.d_expandedKeys = {...this.d_expandedKeys};
|
||||
this.$emit('update:expandedKeys', this.d_expandedKeys);
|
||||
},
|
||||
onNodeClick(event) {
|
||||
if (this.selectionMode != null && event.node.selectable !== false) {
|
||||
const metaSelection = event.nodeTouched ? false : this.metaKeySelection;
|
||||
const _selectionKeys = metaSelection ? this.handleSelectionWithMetaKey(event) : this.handleSelectionWithoutMetaKey(event);
|
||||
|
||||
this.$emit('update:selectionKeys', _selectionKeys);
|
||||
}
|
||||
},
|
||||
handleSelectionWithMetaKey(event) {
|
||||
const originalEvent = event.originalEvent;
|
||||
const node = event.node;
|
||||
const metaKey = (originalEvent.metaKey||originalEvent.ctrlKey);
|
||||
const selected = this.isNodeSelected(node);
|
||||
let _selectionKeys;
|
||||
|
||||
if (selected && metaKey) {
|
||||
if (this.isSingleSelectionMode()) {
|
||||
_selectionKeys = {};
|
||||
}
|
||||
else {
|
||||
_selectionKeys = {...this.selectionKeys};
|
||||
delete _selectionKeys[node.key];
|
||||
}
|
||||
|
||||
this.$emit('node-unselect', node);
|
||||
}
|
||||
else {
|
||||
if (this.isSingleSelectionMode()) {
|
||||
_selectionKeys = {};
|
||||
}
|
||||
else if (this.isMultipleSelectionMode()) {
|
||||
_selectionKeys = !metaKey ? {} : (this.selectionKeys ? {...this.selectionKeys} : {});
|
||||
}
|
||||
|
||||
_selectionKeys[node.key] = true;
|
||||
this.$emit('node-select', node);
|
||||
}
|
||||
|
||||
return _selectionKeys;
|
||||
},
|
||||
handleSelectionWithoutMetaKey(event) {
|
||||
const node = event.node;
|
||||
const selected = this.isNodeSelected(node);
|
||||
let _selectionKeys;
|
||||
|
||||
if (this.isSingleSelectionMode()) {
|
||||
if (selected) {
|
||||
_selectionKeys = {};
|
||||
this.$emit('node-unselect', node);
|
||||
}
|
||||
else {
|
||||
_selectionKeys = {};
|
||||
_selectionKeys[node.key] = true;
|
||||
this.$emit('node-select', node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (selected) {
|
||||
_selectionKeys = {...this.selectionKeys};
|
||||
delete _selectionKeys[node.key];
|
||||
|
||||
this.$emit('node-unselect', node);
|
||||
}
|
||||
else {
|
||||
_selectionKeys = this.selectionKeys ? {...this.selectionKeys} : {};
|
||||
_selectionKeys[node.key] = true;
|
||||
|
||||
this.$emit('node-select', node);
|
||||
}
|
||||
}
|
||||
|
||||
return _selectionKeys;
|
||||
},
|
||||
isSingleSelectionMode() {
|
||||
return this.selectionMode === 'single';
|
||||
},
|
||||
isMultipleSelectionMode() {
|
||||
return this.selectionMode === 'multiple';
|
||||
},
|
||||
onPage(event) {
|
||||
this.d_first = event.first;
|
||||
this.d_rows = event.rows;
|
||||
|
@ -655,6 +734,10 @@ export default {
|
|||
table-layout: auto;
|
||||
}
|
||||
|
||||
.p-treetable-hoverable-rows .p-treetable-tbody > tr.p-highlight {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
.p-treetable-header,
|
||||
.p-treetable-footer {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<tr :class="containerClass">
|
||||
<tr :class="containerClass" @click="onClick" @keydown="onKeyDown" @touchend="onTouchEnd" :style="node.style">
|
||||
<td v-for="(col,i) of columns" :key="col.columnKey||col.field||i" :style="col.bodyStyle" :class="col.bodyClass">
|
||||
<span class="p-treetable-toggler p-unselectable-text" @click="toggle" v-if="col.expander" :style="togglerStyle">
|
||||
<i :class="togglerIcon"></i>
|
||||
|
@ -12,6 +12,7 @@
|
|||
|
||||
<script>
|
||||
import ObjectUtils from '../utils/ObjectUtils';
|
||||
import DomHandler from '../utils/DomHandler';
|
||||
import TreeTableColumnSlot from './TreeTableColumnSlot';
|
||||
|
||||
export default {
|
||||
|
@ -42,6 +43,7 @@ export default {
|
|||
default: 0
|
||||
}
|
||||
},
|
||||
nodeTouched: false,
|
||||
methods: {
|
||||
resolveFieldData(rowData, field) {
|
||||
return ObjectUtils.resolveFieldData(rowData, field);
|
||||
|
@ -49,8 +51,35 @@ export default {
|
|||
toggle() {
|
||||
this.$emit('node-toggle', this.node);
|
||||
},
|
||||
onChildNodeToggle(node) {
|
||||
this.$emit('node-toggle', node);
|
||||
onClick(event) {
|
||||
if (DomHandler.hasClass(event.target, 'p-treetable-toggler') || DomHandler.hasClass(event.target, 'p-treetable-toggler-icon')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isCheckboxSelectionMode()) {
|
||||
this.toggleCheckbox();
|
||||
}
|
||||
else {
|
||||
this.$emit('node-click', {
|
||||
originalEvent: event,
|
||||
nodeTouched: this.nodeTouched,
|
||||
node: this.node
|
||||
});
|
||||
}
|
||||
|
||||
this.nodeTouched = false;
|
||||
},
|
||||
isCheckboxSelectionMode() {
|
||||
return this.selectionMode === 'checkbox';
|
||||
},
|
||||
toggleCheckbox() {
|
||||
|
||||
},
|
||||
onTouchEnd() {
|
||||
this.nodeTouched = true;
|
||||
},
|
||||
onKeyDown(event) {
|
||||
//todo
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
|
@ -33,7 +33,8 @@ const TreeTableRowLoader = {
|
|||
const root = createElement(TreeTableRow, {
|
||||
props: context.props,
|
||||
on: {
|
||||
'node-toggle': context.listeners['node-toggle']
|
||||
'node-toggle': context.listeners['node-toggle'],
|
||||
'node-click': context.listeners['node-click']
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -50,7 +51,8 @@ const TreeTableRowLoader = {
|
|||
let childNodeElement = createElement(TreeTableRowLoader, {
|
||||
props: childNodeProps,
|
||||
on: {
|
||||
'node-toggle': context.listeners['node-toggle']
|
||||
'node-toggle': context.listeners['node-toggle'],
|
||||
'node-click': context.listeners['node-click']
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -405,6 +405,11 @@ export default new Router({
|
|||
path: '/treetable/filter',
|
||||
name: 'treetablefilter',
|
||||
component: () => import('./views/treetable/TreeTableFilterDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/treetable/selection',
|
||||
name: 'treetableselection',
|
||||
component: () => import('./views/treetable/TreeTableSelectionDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/tristatecheckbox',
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<div>
|
||||
<TreeTableSubMenu />
|
||||
|
||||
<div class="content-section introduction">
|
||||
<div class="feature-intro">
|
||||
<h1>TreeTable - Selection</h1>
|
||||
<p>TreeTable supports <b>single</b>, <b>multiple</b> and <b>checkbox</b> as selection modes.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-section implementation">
|
||||
<h3>Single Selection</h3>
|
||||
<TreeTable :value="nodes" selectionMode="single" :selectionKeys.sync="selectedKey1">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
|
||||
<h3>Multiple Selection with MetaKey</h3>
|
||||
<TreeTable :value="nodes" selectionMode="multiple" :selectionKeys.sync="selectedKeys1">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
|
||||
<h3>Multiple Selection without MetaKey</h3>
|
||||
<TreeTable :value="nodes" selectionMode="multiple" :selectionKeys.sync="selectedKeys2" :metaKeySelection="false">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
|
||||
<h3>Checkbox Selection</h3>
|
||||
<TreeTable :value="nodes" selectionMode="checkbox" :selectionKeys.sync="selectedKeys3">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
|
||||
<h3>Events</h3>
|
||||
<TreeTable :value="nodes" selectionMode="single" :selectionKeys.sync="selectedKey2"
|
||||
@node-select="onNodeSelect" @node-unselect="onNodeUnselect">
|
||||
<Column field="name" header="Name" :expander="true"></Column>
|
||||
<Column field="size" header="Size"></Column>
|
||||
<Column field="type" header="Type"></Column>
|
||||
</TreeTable>
|
||||
</div>
|
||||
|
||||
<TreeTableDoc />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NodeService from '../../service/NodeService';
|
||||
import TreeTableDoc from './TreeTableDoc';
|
||||
import TreeTableSubMenu from './TreeTableSubMenu';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectedKey1: null,
|
||||
selectedKey2: null,
|
||||
selectedKeys1: null,
|
||||
selectedKeys2: null,
|
||||
selectedKeys3: null,
|
||||
nodes: null
|
||||
}
|
||||
},
|
||||
nodeService: null,
|
||||
created() {
|
||||
this.nodeService = new NodeService();
|
||||
},
|
||||
mounted() {
|
||||
this.nodeService.getTreeTableNodes().then(data => this.nodes = data);
|
||||
},
|
||||
methods: {
|
||||
onNodeSelect(node) {
|
||||
this.$toast.add({severity:'success', summary: 'Node Selected', detail: node.data.name, life: 3000});
|
||||
},
|
||||
onNodeUnselect(node) {
|
||||
this.$toast.add({severity:'success', summary: 'Node Unselected', detail: node.data.name, life: 3000});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'TreeTableDoc': TreeTableDoc,
|
||||
'TreeTableSubMenu': TreeTableSubMenu
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
button {
|
||||
margin-right: .5em;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue