diff --git a/src/components/tree/Tree.vue b/src/components/tree/Tree.vue index 263d2f088..c9cd119b8 100644 --- a/src/components/tree/Tree.vue +++ b/src/components/tree/Tree.vue @@ -2,7 +2,8 @@
@@ -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: { diff --git a/src/components/tree/TreeNode.vue b/src/components/tree/TreeNode.vue index fbf91cd23..e54369ba7 100644 --- a/src/components/tree/TreeNode.vue +++ b/src/components/tree/TreeNode.vue @@ -1,6 +1,7 @@ @@ -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]; }, diff --git a/src/router.js b/src/router.js index fa8680d94..15c709813 100644 --- a/src/router.js +++ b/src/router.js @@ -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', diff --git a/src/views/tree/TreeSelectionDemo.vue b/src/views/tree/TreeSelectionDemo.vue new file mode 100644 index 000000000..65926ffae --- /dev/null +++ b/src/views/tree/TreeSelectionDemo.vue @@ -0,0 +1,62 @@ + + + + \ No newline at end of file