为啥没有CheckboxTree这样常用的控件?
Closed this issue · 17 comments
Tree本身有select功能,然后某个皮肤实现了选中项是checkbox的样式
在 2015年9月7日,上午12:32,acelan86 notifications@github.com 写道:
—
Reply to this email directly or view it on GitHub.
@otakustay 程序员都是夜猫子啊~
我之前简单看了下,selectNode没有递归选中子节点跟更新父节点的选中状态,stragry里面也没看到,我能求个例子么?
自己写的CheckboxTree继承Tree样式都要重新写,因为ui-type变了
define(function (require) {
var Tree = require('esui/Tree');
var lib = require('esui/lib');
function CheckboxTree() {
Tree.apply(this, arguments);
}
CheckboxTree.prototype = {
constructor: CheckboxTree,
type: 'CheckboxTree',
getItemHTML: function (node) {
var data = {
id: lib.encodeHTML(node.id),
text: lib.encodeHTML(node.text)
};
return lib.format(
'<input type="checkbox"/><span title="${text}">${text}</span>',
data
);
},
dispose : function () {
helper.beforeDispose(this);
helper.dispose(this);
helper.afterDispose(this);
},
.... some other method
};
lib.inherits(CheckboxTree, Tree);
require('esui/main').register(CheckboxTree);
return CheckboxTree;
});
递归选中的功能确实没有,因为有些系统“选中节点”“和选中所有子节点”是不等价的
样式上我明天找找,3.2是肯定有的,3.1不记得了……
在 2015年9月7日,上午12:40,acelan86 notifications@github.com 写道:
@otakustay 程序员都是夜猫子啊~
我之前简单看了下,selectNode没有递归选中子节点跟更新父节点的选中状态,stragry里面也没看到,我能求个例子么?
自己写的CheckboxTree继承Tree样式都要重新写,因为ui-type变了define(function (require) {
var Tree = require('esui/Tree');
var lib = require('esui/lib');function CheckboxTree() { Tree.apply(this, arguments); } CheckboxTree.prototype = { constructor: CheckboxTree, type: 'CheckboxTree', getItemHTML: function (node) { var data = { id: lib.encodeHTML(node.id), text: lib.encodeHTML(node.text) }; return lib.format( '<input type="checkbox"/><span title="${text}">${text}</span>', data ); }, dispose : function () { helper.beforeDispose(this); helper.dispose(this); helper.afterDispose(this); }, .... some other method }; lib.inherits(CheckboxTree, Tree); require('esui/main').register(CheckboxTree); return CheckboxTree;
});
—
Reply to this email directly or view it on GitHub.
@otakustay 谢灰大百忙抽空,还是希望能有个专门的这个ui,个人觉得挺常用的(估计项目业务原因 T_T),没有我就写个了。。
另外,上面还暴露了一个问题,ui的对象能继承,但是style没法继承。。这点怎么折腾?
你需要 prototype.styleType = 'Tre e'这个?
在 2015年9月7日,上午12:58,acelan86 notifications@github.com 写道:
@otakustay 谢灰大百忙抽空,还是希望能有个专门的这个ui,个人觉得挺常用的(估计项目业务原因 T_T),没有我就写个了。。
另外,上面还暴露了一个问题,ui的对象能继承,但是style没法继承。。这点怎么折腾?
—
Reply to this email directly or view it on GitHub.
是!高端,看来是我使用的姿势不对。我去改了,谢谢
http://ecomfe.github.io/esui-family/controls/index.html?control=Tree
这里有个样式,不过确实没有递归选中,递归选中需要自己写一个TreeStrategy
在enableSelectStrategy
中实现
ok~~已经很好了
define(function (require) {
var Tree = require('esui/Tree');
var lib = require('esui/lib');
var helper = require('esui/controlHelper');
var TreeStrategy = require('esui/TreeStrategy');
/**
* 获取checkbox对应的策略树
*/
function getTreeStrategy() {
var strategy = new TreeStrategy({
defaultExpand: 1
});
strategy.enableSelectStrategy = function (tree) {
tree.on(
'select',
function (e) {
this.selectNode(e.node.id);
}
);
tree.on(
'unselect',
function (e) {
tree.unselectNode(e.node.id);
}
);
};
return strategy;
}
/**
* 获取部件的css class
*/
function getClass(tree, part) {
return helper.getPartClasses(tree, part).join(' ');
}
/**
* 获取部件的id
*/
function getId(tree, part) {
return helper.getId(tree, part);
}
function CheckboxTree() {
Tree.apply(this, arguments);
}
CheckboxTree.prototype = {
constructor: CheckboxTree,
type: 'CheckboxTree',
styleType: 'Tree',
getCategory: function () {
return 'input';
},
initOptions: function (options) {
lib.extend(options, {
strategy: getTreeStrategy(),
selectMode: 'multi'
});
Tree.prototype.initOptions.call(this, options);
},
//修改节点展现
getItemHTML: function (node) {
return lib.format(
'<input type="checkbox" id="${cbId}"><span>${text}</span>',
{
cbId: getId(this, 'cb-' + node.id),
text: lib.encodeHTML(node.text)
}
);
},
//重写选中节点逻辑,增加checkbox选中和递归选中
selectNode: function (id, silent, dontRecurse) {
Tree.prototype.selectNode.call(this, id, silent);
lib.g(getId(this, 'cb-' + id)).checked = true;
if (!dontRecurse) {
this.updateChildSelect(id, true, true);
this.updateParentSelect(id, true);
}
},
//重写取消选中逻辑, 增加checkbox取消选中和递归取消
unselectNode: function (id, silent, dontRecurse) {
Tree.prototype.unselectNode.call(this, id, silent);
lib.g(getId(this, 'cb-' + id)).checked = false;
if (!dontRecurse) {
this.updateChildSelect(id, false, true);
this.updateParentSelect(id, true);
}
},
//向上检查是否需要取消父节点选中或者选中
updateParentSelect: function (id) {
var nodeData,
parentId,
parentData;
if (
(nodeData = this.nodeIndex[id]) &&
(parentId = nodeData.parentId) &&
(parentData = this.nodeIndex[parentId])
) {
children = parentData.children;
childLen = children instanceof Array && children.length;
checked = true;
count = childLen;
len = childLen;
while (childLen--) {
//节点是否为选中
if (!this.selectedNodeIndex[children[childLen].id]) {
count--;
checked = false;
}
}
if (count && !checked) {
this.unselectNode(parentId, true, true);
} else {
checked
? this.selectNode(parentId, true, true)
: this.unselectNode(parentId, true, true);
}
}
parentId && this.updateParentSelect(parentId);
},
//向下检查是否需要取消子节点选中或者选中
updateChildSelect: function (id, checked) {
var me = this;
var nodeData = this.nodeIndex[id];
var children = nodeData.children;
var childLen = children instanceof Array && children.length;
var data;
if (childLen) {
while (childLen--) {
data = children[childLen];
checked
? this.selectNode(data.id, true)
: this.unselectNode(data.id, true);
}
}
},
dispose : function () {
helper.beforeDispose(this);
helper.dispose(this);
helper.afterDispose(this);
}
};
lib.inherits(CheckboxTree, Tree);
require('esui/main').register(CheckboxTree);
return CheckboxTree;
});
silent那块还没决定好怎么处理,先直接全部禁掉了
重开下,两个问题:
1、我觉得CheckboxTree应该属于InputControl,应该继承自InputControl和Tree, 这个该怎么写,能多继承么,ui
2、CheckboxTree的fire事件的参数应该是啥?当前节点还是包含被动递归选中的所有节点,就是selectedNodes里面的东西
prototype.getCategory = function () {
return 'input';
}
@otakustay 灰大,我又来了,还是递归选中的问题
如果我调用tree的selectNode方法去选中一个节点,这时候会触发selectionchange事件,但是这时候我的递归还没完成,所以selectionchange事件里面getSelectedNodes获取不到所有被选中的nodes
这样的情况怎么处理好?
如果我先做递归,然后在执行selectNode方法,那么我在递归中需要判断
//节点是否为选中
if (!this.selectedNodeIndex[children[childLen].id]) {
的处理又不能正确判断了
如果我自己做一套选中index的缓存,不用tree自己的,又感觉挺不爽的。。所以。。
CheckboxTree的代码在上面的讨论中已经给出了
.....我用这样来解决,有点无力....
/**
* 为了不改变Tree的代码,将内部方法重新实现一遍
* 用于后面进行数据管理
*/
removeSelectedNode: function (node) {
if (this.selectedNodeIndex[node.id]) {
delete this.selectedNodeIndex[node.id];
for (var i = 0; i < this.selectedNodes.length; i++) {
if (this.selectedNodes[i] === node) {
this.selectedNodes.splice(i, 1);
}
}
return true;
}
return false;
},
//重写选中节点逻辑,增加checkbox选中和递归选中
selectNode: function (id, silent, dontRecurse) {
var node = this.nodeIndex[id];
//先写入
this.addSelectedNode(node);
lib.g(getId(this, 'cb-' + id)).checked = true;
if (!dontRecurse) {
this.updateChildSelect(id, true, true);
this.updateParentSelect(id, true);
}
//在删除,让后面可以触发
this.removeSelectedNode(node);
Tree.prototype.selectNode.call(this, id, silent);
},
//重写取消选中逻辑, 增加checkbox取消选中和递归取消
unselectNode: function (id, silent, dontRecurse) {
var node = this.nodeIndex[id];
//先删除
this.removeSelectedNode(node);
lib.g(getId(this, 'cb-' + id)).checked = false;
if (!dontRecurse) {
this.updateChildSelect(id, false, true);
this.updateParentSelect(id, true);
}
//再写入,让后面可以触发
this.addSelectedNode(node);
Tree.prototype.unselectNode.call(this, id, silent);
},
看上去似乎应该你递归时先silent
不触发事件,全部完成后手动触发一次selectionchange
事件?
是的。。就是比如unselectNode的时候
//先删除
this.removeSelectedNode(node);
...//递归
//再写入,让后面可以触发
this.addSelectedNode(node);
这里比较没办法,如果不先从数据上删除,后面递归无法正确执行,如果数据删除后不重新写入(恢复),后面的事件无法触发,只能想到这么做了,在不修改Tree的前提下,不知道是否有更好的方法,或者需要对Tree的设计进行重新思考
我感觉直接调用fire
触发事件就好了啊……
好。。像。。。是。。。的。。。。