diff --git a/src/components/treetable/TreeTable.vue b/src/components/treetable/TreeTable.vue
index f6d2930c8..362cbfad2 100644
--- a/src/components/treetable/TreeTable.vue
+++ b/src/components/treetable/TreeTable.vue
@@ -36,8 +36,8 @@
+ :expandedKeys="d_expandedKeys" @node-toggle="onNodeToggle"
+ :selectionMode="selectionMode" :selectionKeys="selectionKeys" @node-click="onNodeClick" @checkbox-change="onCheckboxChange">
@@ -232,7 +232,7 @@ export default {
this.$emit('update:expandedKeys', this.d_expandedKeys);
},
onNodeClick(event) {
- if (this.selectionMode != null && event.node.selectable !== false) {
+ if (this.rowSelectionMode && event.node.selectable !== false) {
const metaSelection = event.nodeTouched ? false : this.metaKeySelection;
const _selectionKeys = metaSelection ? this.handleSelectionWithMetaKey(event) : this.handleSelectionWithoutMetaKey(event);
@@ -304,6 +304,14 @@ export default {
return _selectionKeys;
},
+ onCheckboxChange(event) {
+ this.$emit('update:selectionKeys', event.selectionKeys);
+
+ if (event.check)
+ this.$emit('node-select', event.node);
+ else
+ this.$emit('node-unselect', event.node);
+ },
isSingleSelectionMode() {
return this.selectionMode === 'single';
},
@@ -595,7 +603,7 @@ export default {
computed: {
containerClass() {
return ['p-treetable p-component', {
- 'p-treetable-hoverable-rows': (this.rowHover || this.selectionMode),
+ 'p-treetable-hoverable-rows': (this.rowHover || this.rowSelectionMode),
'p-treetable-auto-layout': this.autoLayout
}];
},
@@ -673,6 +681,15 @@ export default {
paginatorBottom() {
return this.paginator && (this.paginatorPosition !== 'top' || this.paginatorPosition === 'both');
},
+ singleSelectionMode() {
+ return this.selectionMode && this.selectionMode === 'single';
+ },
+ multipleSelectionMode() {
+ return this.selectionMode && this.selectionMode === 'multiple';
+ },
+ rowSelectionMode() {
+ return this.singleSelectionMode || this.multipleSelectionMode;
+ },
totalRecordsLength() {
if (this.lazy) {
return this.totalRecords;
diff --git a/src/components/treetable/TreeTableRow.vue b/src/components/treetable/TreeTableRow.vue
index ca4a6edad..fc786bd82 100644
--- a/src/components/treetable/TreeTableRow.vue
+++ b/src/components/treetable/TreeTableRow.vue
@@ -4,6 +4,14 @@
+
{{resolveFieldData(node.data, col.field)}}
|
@@ -22,6 +30,10 @@ export default {
type: null,
default: null
},
+ parentNode: {
+ type: null,
+ default: null
+ },
columns: {
type: null,
default: null
@@ -52,34 +64,82 @@ export default {
this.$emit('node-toggle', this.node);
},
onClick(event) {
- if (DomHandler.hasClass(event.target, 'p-treetable-toggler') || DomHandler.hasClass(event.target, 'p-treetable-toggler-icon')) {
+ let targetNode = event.target.nodeName;
+ if (targetNode === 'INPUT' || targetNode === 'BUTTON' || targetNode === 'A' || DomHandler.hasClass(event.target, 'p-clickable')
+ || DomHandler.hasClass(event.target, 'p-treetable-toggler') || DomHandler.hasClass(event.target.parentElement, 'p-treetable-toggler')) {
return;
}
- if (this.isCheckboxSelectionMode()) {
- this.toggleCheckbox();
- }
- else {
- this.$emit('node-click', {
+ 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
+ },
+ toggleCheckbox() {
+ let _selectionKeys = this.selectionKeys ? {...this.selectionKeys} : {};
+ const _check = !this.checked;
+
+ this.propagateDown(this.node, _check, _selectionKeys);
+
+ this.$emit('checkbox-change', {
+ node: this.node,
+ check: _check,
+ selectionKeys: _selectionKeys
+ });
+ },
+ propagateDown(node, check, selectionKeys) {
+ if (check)
+ selectionKeys[node.key] = {checked: true, partialChecked: false};
+ else
+ delete selectionKeys[node.key];
+
+ if (node.children && node.children.length) {
+ for (let child of node.children) {
+ this.propagateDown(child, check, selectionKeys);
+ }
+ }
+ },
+ propagateUp(event) {
+ let check = event.check;
+ let _selectionKeys = {...event.selectionKeys};
+ let checkedChildCount = 0;
+ let childPartialSelected = false;
+
+ for(let child of this.node.children) {
+ if(_selectionKeys[child.key] && _selectionKeys[child.key].checked)
+ checkedChildCount++;
+ else if(_selectionKeys[child.key] && _selectionKeys[child.key].partialChecked)
+ childPartialSelected = true;
+ }
+
+ if(check && checkedChildCount === this.node.children.length) {
+ _selectionKeys[this.node.key] = {checked: true, partialChecked: false};
+ }
+ else {
+ if (!check) {
+ delete _selectionKeys[this.node.key];
+ }
+
+ if(childPartialSelected || (checkedChildCount > 0 && checkedChildCount !== this.node.children.length))
+ _selectionKeys[this.node.key] = {checked: false, partialChecked: true};
+ else
+ _selectionKeys[this.node.key] = {checked: false, partialChecked: false};
+ }
+
+ this.$emit('checkbox-change', {
+ node: event.node,
+ check: event.check,
+ selectionKeys: _selectionKeys
+ });
}
},
computed: {
@@ -111,6 +171,21 @@ export default {
},
childLevel() {
return this.level + 1;
+ },
+ checkboxSelectionMode() {
+ return this.selectionMode === 'checkbox';
+ },
+ checkboxClass() {
+ return ['p-checkbox-box', {'p-highlight': this.checked}];
+ },
+ checkboxIcon() {
+ return ['p-checkbox-icon p-c', {'pi pi-check': this.checked, 'pi pi-minus': this.partialChecked}];
+ },
+ checked() {
+ return this.selectionKeys ? this.selectionKeys[this.node.key] && this.selectionKeys[this.node.key].checked: false;
+ },
+ partialChecked() {
+ return this.selectionKeys ? this.selectionKeys[this.node.key] && this.selectionKeys[this.node.key].partialChecked: false;
}
},
components: {
diff --git a/src/components/treetable/TreeTableRowLoader.vue b/src/components/treetable/TreeTableRowLoader.vue
index 4c91c0dca..b009a74a2 100644
--- a/src/components/treetable/TreeTableRowLoader.vue
+++ b/src/components/treetable/TreeTableRowLoader.vue
@@ -34,7 +34,8 @@ const TreeTableRowLoader = {
props: context.props,
on: {
'node-toggle': context.listeners['node-toggle'],
- 'node-click': context.listeners['node-click']
+ 'node-click': context.listeners['node-click'],
+ 'checkbox-change': context.listeners['checkbox-change']
}
});
@@ -46,13 +47,47 @@ const TreeTableRowLoader = {
for (let childNode of node.children) {
let childNodeProps = {...context.props};
childNodeProps.node = childNode;
+ childNodeProps.parentNode = node;
childNodeProps.level = context.props.level + 1;
let childNodeElement = createElement(TreeTableRowLoader, {
props: childNodeProps,
on: {
'node-toggle': context.listeners['node-toggle'],
- 'node-click': context.listeners['node-click']
+ 'node-click': context.listeners['node-click'],
+ 'checkbox-change': (event) => {
+ let check = event.check;
+ let _selectionKeys = {...event.selectionKeys};
+ let checkedChildCount = 0;
+ let childPartialSelected = false;
+
+ for(let child of node.children) {
+ if(_selectionKeys[child.key] && _selectionKeys[child.key].checked)
+ checkedChildCount++;
+ else if(_selectionKeys[child.key] && _selectionKeys[child.key].partialChecked)
+ childPartialSelected = true;
+ }
+
+ if(check && checkedChildCount === node.children.length) {
+ _selectionKeys[node.key] = {checked: true, partialChecked: false};
+ }
+ else {
+ if (!check) {
+ delete _selectionKeys[node.key];
+ }
+
+ if(childPartialSelected || (checkedChildCount > 0 && checkedChildCount !== node.children.length))
+ _selectionKeys[node.key] = {checked: false, partialChecked: true};
+ else
+ _selectionKeys[node.key] = {checked: false, partialChecked: false};
+ }
+
+ context.listeners['checkbox-change']({
+ node: event.node,
+ check: event.check,
+ selectionKeys: _selectionKeys
+ });
+ }
}
});