bootstrap treeview預設不提供全選 / 全部取消操作, 需要開發者自定義. 自定義效果如下, 點選父節點, 子節點全部選中, 再次點選, 子節點全部取消選中. 在筆者的情況下, 需要實作父節點的單獨選中, 是以這裡做了子節點全部不選中的情況下, 依然保持父節點單獨選中狀态.
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2UmNkFjM5QWN2UTOzMjY5M2M2UWOkBzNyIzNmFGO4QTNhZWMyMmZi9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
<div id="modal-departments-lessonManage" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modal-detail-title" data-backdrop="static" >
<div class="modal-dialog" style="width: 80%;">
<div class="modal-content" style="min-height:500px">
<div class="modal-header">
<button class="close" type="button" data-dismiss="modal">
<span>×</span>
</button>
<h5 id="modal-detail-title" class="modal-title">選擇必修部門</h5>
</div>
<div class="modal-body" style="min-height:380px;padding:30px 25px;">
<div class="form-group">
<button class="btn btn-primary" id="expandTree_btn_lessonManage">展開全部</button>
<button class="btn btn-primary" id="collapseTree_btn_lessonManage">折疊全部</button>
<div class="col-sm-6" style="padding-left:0;">
<input id="search-departmentsTree-lessonManage" class="col-sm-5 form-control" type="text" placeholder="輸入關鍵字, 比對部門會高亮顯示"/>
</div>
</div>
<div id="tree-departments-lessonManage"></div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-dismiss="modal" id="btn-confirm-departments-lessonManage">确定</button>
<button class="btn btn-default" data-dismiss="modal">關閉</button>
</div>
</div>
</div>
</div>
JavaScript代碼如下:
var checkableTree_lessonMange = {};
function buildLessonDepartmentTree(treeData, id) {
checkableTree_lessonMange = $('#tree-departments-lessonManage').treeview({
data: treeData,
showIcon: false,
color: "#428bca",
showCheckbox: true,
selectedColor: "#428bca",
selectedBackColor: "#eee",
nodeIcon: "glyphicon glyphicon-user",
onNodeChecked: function(event, node) { // 選中事件
var childrenIds = listChildrenIds(node); // 擷取所有子節點ID, 包括目前節點ID
checkableTree_lessonMange.treeview('checkNode', [childrenIds, { silent: true }]); //全部選中
handleParentCheckedStatus(node); // 處理父節點狀态
},
onNodeUnchecked: function(event, node) { //取消選中事件
var allChildrenNodeIds = listChildrenIds(node); //擷取所有子節點
var uncheckedchildrenIds = getUncheckedChildrenIds(node); //擷取未被選中的子節點
if (allChildrenNodeIds && uncheckedchildrenIds.length == 0) { //有子節點且都被選中情況下,取消選中所有子節點. 加判斷防止觸發父節點uncheck事件導緻兄弟節點及兄弟節點的子節點觸發uncheck事件
checkableTree_lessonMange.treeview('uncheckNode', [allChildrenNodeIds, { silent: true }]);
}
}
});
$('#expandTree_btn_lessonManage').click(function() { // 展開所有節點
checkableTree_lessonMange.treeview('expandAll');
});
$('#collapseTree_btn_lessonManage').click(function() { //合并所有節點
checkableTree_lessonMange.treeview('collapseAll');
});
$('#search-departmentsTree-lessonManage').on('input', function (e) { // 搜尋指定節點, 并高亮顯示
checkableTree_lessonMange.treeview('search', [ $(this).val(), { ignoreCase: false, exactMatch: false }]);
});
}
// 處理父節點的選中狀态, 在這個方法中能夠處理是否當所有子節點被選中時自動選中父節點, 任意一子節點取消選中時取消選中父節點
function handleParentCheckedStatus(node) {
var parentNode = $('#tree-departments-lessonManage').treeview("getNode", node.parentId);
if (parentNode.nodes) {
var checkedCount = 0;
for (childIndex in parentNode.nodes) {
if (!parentNode.nodes[childIndex].state.checked) {
return;
}
checkedCount++;
}
$('#tree-departments-lessonManage').treeview("checkNode", parentNode.nodeId);
setParentNodeCheck(parentNode);
}
}
// 擷取指定節點下所有未被選中的子節點ID
function getUncheckedChildrenIds(parentNode) {
var children = parentNode.nodes, uncheckedIds = []; //目前節點子集中未被選中的集合
if (!children) {
return uncheckedIds;
}
for (nodeIndex in children) {
!children[nodeIndex].state.checked ? uncheckedIds.push(children[nodeIndex].nodeId) : '';
if (children[nodeIndex].nodes) {
var recursionNodes = getUncheckedChildrenIds[nodeIndex];
for (recursionIndex in recursionNodes) {
!recursionNodes[recursionIndex].state.checked ? uncheckedIds.push(recursionNodes[recursionIndex]) : '';
}
}
}
return uncheckedIds;
}
// 擷取指定節點下的所有子節點ID
function listChildrenIds(parentNode) {
var childrenIds = [], children = parentNode.nodes;
if (!children) {
childrenIds.push(parentNode.nodeId);
return childrenIds;
}
for (nodeIndex in children) {
childrenIds.push(children[nodeIndex].nodeId);
if (children[nodeIndex].nodes) {
var recursionNodes = listChildrenIds(children[nodeIndex]);
for (recursionIndex in recursionNodes) {
childrenIds.push(recursionNodes[recursionIndex]);
}
}
}
return childrenIds;
}