Add single and multiple selection

pull/41/head
cagataycivici 2019-08-01 12:40:15 +03:00
parent e4e5e3c607
commit 56839ca196
4 changed files with 236 additions and 7 deletions

View File

@ -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: {

View File

@ -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];
},

View File

@ -361,6 +361,11 @@ export default new Router({
name: 'tree',
component: () => import('./views/tree/TreeDemo.vue')
},
{
path: '/tree/selection',
name: 'treeselectiın',
component: () => import('./views/tree/TreeSelectionDemo.vue')
},
{
path: '/tristatecheckbox',
name: 'tristatecheckbox',

View File

@ -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>