Tree: add check-descendants attribute

pull/6325/head
Dreamacro 2017-07-28 16:54:07 +08:00 committed by 杨奕
parent 54e5cd2340
commit 41c19249ab
3 changed files with 143 additions and 47 deletions

View File

@ -22,6 +22,8 @@ export const getChildState = node => {
}; };
const reInitChecked = function(node) { const reInitChecked = function(node) {
if (node.childNodes.length === 0) return;
const {all, none, half} = getChildState(node.childNodes); const {all, none, half} = getChildState(node.childNodes);
if (all) { if (all) {
node.checked = true; node.checked = true;
@ -42,22 +44,6 @@ const reInitChecked = function(node) {
} }
}; };
const initLazyLoadChild = node => {
const childNodes = node.childNodes;
if (node.checked) {
for (let i = 0, j = childNodes.length; i < j; i++) {
const child = childNodes[i];
if (!child.disabled) {
child.checked = true;
}
}
}
const parent = node.parent;
if (!parent || parent.level === 0) return;
reInitChecked(parent);
};
const getPropertyFromData = function(node, prop) { const getPropertyFromData = function(node, prop) {
const props = node.store.props; const props = node.store.props;
const data = node.data || {}; const data = node.data || {};
@ -261,7 +247,11 @@ export default class Node {
if (this.shouldLoadData()) { if (this.shouldLoadData()) {
this.loadData((data) => { this.loadData((data) => {
if (data instanceof Array) { if (data instanceof Array) {
initLazyLoadChild(this); if (this.checked) {
this.setChecked(true, true);
} else {
reInitChecked(this);
}
done(); done();
} }
}); });
@ -300,45 +290,52 @@ export default class Node {
setChecked(value, deep, recursion, passValue) { setChecked(value, deep, recursion, passValue) {
this.indeterminate = value === 'half'; this.indeterminate = value === 'half';
this.checked = value === true; this.checked = value === true;
let { all, allWithoutDisable } = getChildState(this.childNodes);
if (this.childNodes.length && (!all && allWithoutDisable)) { if (this.store.checkStrictly) return;
this.checked = false;
value = false;
}
const handleDescendants = (lazy) => { if (!(this.shouldLoadData() && !this.store.checkDescendants)) {
if (deep && !lazy) { let { all, allWithoutDisable } = getChildState(this.childNodes);
const childNodes = this.childNodes;
for (let i = 0, j = childNodes.length; i < j; i++) { if (!this.isLeaf && (!all && allWithoutDisable)) {
const child = childNodes[i]; this.checked = false;
passValue = passValue || value !== false; value = false;
const isCheck = child.disabled ? child.checked : passValue;
child.setChecked(isCheck, deep, true, passValue);
}
const { half, all } = getChildState(childNodes);
if (!all) {
this.checked = all;
this.indeterminate = half;
}
} }
};
if (!this.store.checkStrictly && this.shouldLoadData()) { const handleDescendants = () => {
// Only work on lazy load data. if (deep) {
this.loadData(() => { const childNodes = this.childNodes;
handleDescendants(true); for (let i = 0, j = childNodes.length; i < j; i++) {
}, { const child = childNodes[i];
checked: value !== false passValue = passValue || value !== false;
}); const isCheck = child.disabled ? child.checked : passValue;
} else { child.setChecked(isCheck, deep, true, passValue);
handleDescendants(); }
const { half, all } = getChildState(childNodes);
if (!all) {
this.checked = all;
this.indeterminate = half;
}
}
};
if (this.shouldLoadData()) {
// Only work on lazy load data.
this.loadData(() => {
handleDescendants();
reInitChecked(this);
}, {
checked: value !== false
});
return;
} else {
handleDescendants();
}
} }
const parent = this.parent; const parent = this.parent;
if (!parent || parent.level === 0) return; if (!parent || parent.level === 0) return;
if (!this.store.checkStrictly && !recursion) { if (!recursion) {
reInitChecked(parent); reInitChecked(parent);
} }
} }

View File

@ -53,6 +53,10 @@
type: Boolean, type: Boolean,
default: true default: true
}, },
checkDescendants: {
type: Boolean,
default: false
},
autoExpandParent: { autoExpandParent: {
type: Boolean, type: Boolean,
default: true default: true
@ -180,6 +184,7 @@
load: this.load, load: this.load,
currentNodeKey: this.currentNodeKey, currentNodeKey: this.currentNodeKey,
checkStrictly: this.checkStrictly, checkStrictly: this.checkStrictly,
checkDescendants: this.checkDescendants,
defaultCheckedKeys: this.defaultCheckedKeys, defaultCheckedKeys: this.defaultCheckedKeys,
defaultExpandedKeys: this.defaultExpandedKeys, defaultExpandedKeys: this.defaultExpandedKeys,
autoExpandParent: this.autoExpandParent, autoExpandParent: this.autoExpandParent,

View File

@ -522,6 +522,100 @@ describe('Tree', () => {
}, 100); }, 100);
}); });
it('lazy defaultChecked', done => {
vm = getTreeVm(':props="defaultProps" node-key="id" lazy :load="loadNode" show-checkbox', {
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ label: 'region1', id: this.count++ }, { label: 'region2', id: this.count++ }]);
}
if (node.level > 4) return resolve([]);
setTimeout(() => {
resolve([{
label: 'zone' + this.count,
id: this.count++
}, {
label: 'zone' + this.count,
id: this.count++
}]);
}, 50);
}
}
});
const tree = vm.$children[0];
const firstNode = document.querySelector('.el-tree-node__content');
const initStatus = firstNode.querySelector('.is-indeterminate');
expect(initStatus).to.equal(null);
tree.store.setCheckedKeys([3]);
firstNode.querySelector('.el-tree-node__expand-icon').click();
setTimeout(() => {
const clickStatus = firstNode.querySelector('.is-indeterminate');
expect(clickStatus).to.not.equal(null);
const child = document.querySelectorAll('.el-tree-node__content')[1];
expect(child.querySelector('input').checked).to.equal(true);
done();
}, 300);
});
it('lazy expandOnChecked', done => {
vm = getTreeVm(':props="defaultProps" node-key="id" lazy :load="loadNode" show-checkbox check-descendants', {
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ label: 'region1', id: this.count++ }, { label: 'region2', id: this.count++ }]);
}
if (node.level > 4) return resolve([]);
setTimeout(() => {
resolve([{
label: 'zone' + this.count,
id: this.count++
}, {
label: 'zone' + this.count,
id: this.count++
}]);
}, 50);
}
}
});
const tree = vm.$children[0];
tree.store.setCheckedKeys([1]);
setTimeout(() => {
const id5 = document.querySelectorAll('.el-tree-node__content')[3];
expect(id5.querySelector('input').checked).to.equal(true);
done();
}, 300);
});
it('lazy without expandOnChecked', done => {
vm = getTreeVm(':props="defaultProps" node-key="id" lazy :load="loadNode" show-checkbox', {
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ label: 'region1', id: this.count++ }, { label: 'region2', id: this.count++ }]);
}
if (node.level > 4) return resolve([]);
setTimeout(() => {
resolve([{
label: 'zone' + this.count,
id: this.count++
}, {
label: 'zone' + this.count,
id: this.count++
}]);
}, 50);
}
}
});
const tree = vm.$children[0];
tree.store.setCheckedKeys([1]);
setTimeout(() => {
const nodes = document.querySelectorAll('.el-tree-node__content');
expect(nodes[0].querySelector('input').checked).to.equal(true);
expect(nodes.length).to.equal(2);
done();
}, 300);
});
it('accordion', done => { it('accordion', done => {
vm = getTreeVm(':props="defaultProps" accordion'); vm = getTreeVm(':props="defaultProps" accordion');
const firstNode = vm.$el.querySelector('.el-tree-node__content'); const firstNode = vm.$el.querySelector('.el-tree-node__content');