Add single and multiple selection
parent
e4e5e3c607
commit
56839ca196
|
@ -2,7 +2,8 @@
|
|||
<div :class="containerClass">
|
||||
<ul class="p-tree-container" role="tree">
|
||||
<TreeNode v-for="node of value" :key="node.key" :node="node"
|
||||
:expandedKeys="d_expandedKeys" @toggle="onNodeToggle"></TreeNode>
|
||||
:expandedKeys="d_expandedKeys" @node-toggle="onNodeToggle" @node-click="onNodeClick"
|
||||
:selectionMode="selectionMode" :selectionKeys="selectionKeys"></TreeNode>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -19,6 +20,34 @@ export default {
|
|||
expandedKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionMode: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
metaKeySelection: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
propagateSelectionDown: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
propagateSelectionUp: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: 'pi pi-spinner'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -46,11 +75,106 @@ 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) {
|
||||
let _selectionKeys;
|
||||
|
||||
if (this.isCheckboxSelectionMode()) {
|
||||
|
||||
}
|
||||
else {
|
||||
const metaSelection = event.nodeTouched ? false : this.metaKeySelection;
|
||||
_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.selected;
|
||||
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.isSelected(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;
|
||||
},
|
||||
isCheckboxSelectionMode() {
|
||||
return this.selectionMode === 'checkbox';
|
||||
},
|
||||
isSingleSelectionMode() {
|
||||
return this.selectionMode === 'single';
|
||||
},
|
||||
isMultipleSelectionMode() {
|
||||
return this.selectionMode === 'multiple';
|
||||
},
|
||||
isSelected(node) {
|
||||
return (this.selectionMode && this.selectionKeys) ? this.selectionKeys[node.key] === true : false;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return 'p-tree p-component';
|
||||
return ['p-tree p-component', {
|
||||
'p-tree-selectable': this.selectionMode != null,
|
||||
'p-tree-loading': this.loading
|
||||
}];
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<li :class="containerClass">
|
||||
<div class="p-treenode-content" tabindex="0" role="treeitem" @click="onClick" @keydown="onKeyDown" :aria-expanded="expanded">
|
||||
<div :class="contentClass" tabindex="0" role="treeitem" :aria-expanded="expanded"
|
||||
@click="onClick" @keydown="onKeyDown" @touchend="onTouchEnd">
|
||||
<span class="p-tree-toggler p-unselectable-text p-link" @click="toggle">
|
||||
<span :class="toggleIcon"></span>
|
||||
</span>
|
||||
|
@ -9,7 +10,8 @@
|
|||
</div>
|
||||
<ul class="p-treenode-children" role="group" v-if="hasChildren && expanded">
|
||||
<sub-treenode v-for="childNode of node.children" :key="childNode.key" :node="childNode"
|
||||
:expandedKeys="expandedKeys" @toggle="onChildNodeToggle"></sub-treenode>
|
||||
:expandedKeys="expandedKeys" @node-toggle="onChildNodeToggle" @node-click="onChildNodeClick"
|
||||
:selectionMode="selectionMode" :selectionKeys="selectionKeys"></sub-treenode>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
|
@ -27,17 +29,41 @@ export default {
|
|||
expandedKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionKeys: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
selectionMode: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
nodeTouched: false,
|
||||
methods: {
|
||||
toggle() {
|
||||
this.$emit('toggle', this.node);
|
||||
this.$emit('node-toggle', this.node);
|
||||
},
|
||||
onChildNodeToggle(node) {
|
||||
this.$emit('toggle', node);
|
||||
this.$emit('node-toggle', node);
|
||||
},
|
||||
onClick() {
|
||||
onClick(event) {
|
||||
if (DomHandler.hasClass(event.target, 'p-tree-toggler') || DomHandler.hasClass(event.target, 'p-tree-toggler-icon')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$emit('node-click', {
|
||||
originalEvent: event,
|
||||
nodeTouched: this.nodeTouched,
|
||||
node: this.node
|
||||
});
|
||||
this.nodeTouched = false;
|
||||
},
|
||||
onChildNodeClick(event) {
|
||||
this.$emit('node-click', event);
|
||||
},
|
||||
onTouchEnd() {
|
||||
this.nodeTouched = true;
|
||||
},
|
||||
onKeyDown(event) {
|
||||
const nodeElement = event.target.parentElement;
|
||||
|
@ -141,9 +167,21 @@ export default {
|
|||
leaf() {
|
||||
return this.node.leaf === false ? false : !(this.node.children && this.node.children.length);
|
||||
},
|
||||
selectable() {
|
||||
return this.node.selectable === false ? false : this.selectionMode != null;
|
||||
},
|
||||
selected() {
|
||||
return (this.selectionMode && this.selectionKeys) ? this.selectionKeys[this.node.key] === true : false;
|
||||
},
|
||||
containerClass() {
|
||||
return ['p-treenode', {'p-treenode-leaf': this.leaf}];
|
||||
},
|
||||
contentClass() {
|
||||
return ['p-treenode-content', {
|
||||
'p-treenode-selectable': this.selectable,
|
||||
'p-highlight': this.selected
|
||||
}];
|
||||
},
|
||||
icon() {
|
||||
return ['p-treenode-icon', this.node.icon];
|
||||
},
|
||||
|
|
|
@ -360,6 +360,11 @@ export default new Router({
|
|||
path: '/tree',
|
||||
name: 'tree',
|
||||
component: () => import('./views/tree/TreeDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/tree/selection',
|
||||
name: 'treeselectiın',
|
||||
component: () => import('./views/tree/TreeSelectionDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/tristatecheckbox',
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<div>
|
||||
<TreeSubMenu />
|
||||
|
||||
<div class="content-section introduction">
|
||||
<div class="feature-intro">
|
||||
<h1>Tree - Selection</h1>
|
||||
<p>Tree 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>
|
||||
<Tree :value="nodes" selectionMode="single" :selectionKeys.sync="selectedKey"></Tree>
|
||||
{{selectedKey}}
|
||||
|
||||
<h3>Multiple Selection with MetaKey</h3>
|
||||
<Tree :value="nodes" selectionMode="multiple" :selectionKeys.sync="selectedKeys1"></Tree>
|
||||
{{selectedKeys1}}
|
||||
|
||||
<h3>Multiple Selection without MetaKey</h3>
|
||||
<Tree :value="nodes" selectionMode="multiple" :selectionKeys.sync="selectedKeys2" :metaKeySelection="false"></Tree>
|
||||
{{selectedKeys2}}
|
||||
</div>
|
||||
|
||||
<TreeDoc />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import NodeService from '../../service/NodeService';
|
||||
import TreeDoc from './TreeDoc';
|
||||
import TreeSubMenu from './TreeSubMenu';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectedKey: null,
|
||||
selectedKeys1: null,
|
||||
selectedKeys2: null,
|
||||
selectedKeys3: null,
|
||||
nodes: null
|
||||
}
|
||||
},
|
||||
nodeService: null,
|
||||
created() {
|
||||
this.nodeService = new NodeService();
|
||||
},
|
||||
mounted() {
|
||||
this.nodeService.getTreeNodes().then(data => this.nodes = data);
|
||||
},
|
||||
components: {
|
||||
'TreeDoc': TreeDoc,
|
||||
'TreeSubMenu': TreeSubMenu
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
button {
|
||||
margin-right: .5em;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue