AngularJS:可扩展的递归树表
AngularJS : Expandable recursive tree table
我正在研究角数据树递归表。因此,我们的想法是抛出tree-data(不知道树的深度),并将树呈现为带有可扩展节点的表。现在我成功地通过递归调用模板在
表中创建了一个表这里是代码,或者你可以在这里看到它的运行:jsfiddle
<script type="text/ng-template" id="tree_item.html">
<tr style="width:100%">
<td><i class="fa fa-folder-open"></i></td>
<td>
{{data.name}}
<div id="expanded-data">
<table class="table table-striped" id="nested-table">
<div ng-repeat="data in data.nodes" ng-include="'tree_item.html'"> </div>
</table>
</div>
</td>
</tr>
</script>
<table class="table table-striped">
<thead>
<tr>
<th style="width:30px;"><i ng-click="loadItems()" class="fa fa-refresh blueicon"></i></th>
<th style="width:auto">Data tree</th>
</tr>
</thead>
<tbody ng-repeat="data in treeData" ng-include="'tree_item.html'">
</tbody>
</table>
现在我被困在下一步,这是启用toggle expand &单击文件夹图标时折叠,然后将child-node设置为display= none。
我尝试了一些ng-switch,但没有成功。你们有什么好主意吗?
谢谢你
您可以考虑使用树形网格。
demo: 可扩展网格
<tree-gird tree-data="tree_data"></tree-grid>
提供树结构数据、列定义和想要展开的属性。
提供一个树结构的数据,列定义和一个你想在你的控制器中展开的属性。
$scope.tree_data = [
{Name:"USA",Area:9826675,Population:318212000,TimeZone:"UTC -5 to -10",
children:[
{Name:"California", Area:423970,Population:38340000, TimeZone:"Pacific Time",
children:[
{Name:"San Francisco", Area:231,Population:837442,TimeZone:"PST"},
{Name:"Los Angeles", Area:503,Population:3904657,TimeZone:"PST"}
]
},
{Name:"Illinois", Area:57914,Population:12882135,TimeZone:"Central Time Zone",
children:[
{Name:"Chicago", Area:234,Population:2695598,TimeZone:"CST"}
]
}
]
},
{Name:"Texas",Area:268581,Population:26448193,TimeZone:"Mountain"}
];
可选地,您可以定义列定义,您希望在其上使用展开和折叠的属性
$scope.col_defs = [
{ field: "Description"},
{ field: "DemographicId", displayName: "Demographic Id"},
{ field: "ParentId", displayName: "Parent Id"},
{ field: "Area"},
{ field: "Population"},
{ field: "TimeZone", displayName: "Time Zone"}
];
$scope.expanding_property = "Name";
详细信息:https://github.com/khan4019/tree-grid-directive
在此处添加ng-if
<div id="expanded-data" data-ng-if="childrenVisible">
,并给你的树项一个属性来定义它们的子元素的可见性。设置属性为true或false(如果你想要false,就不要默认添加),并实现toggleChildren函数,该函数通过点击toggleButton(文件夹)来调用
scope.toggleChildren = function () {
scope.item.childrenVisible = !scope.item.childrenVisible;
}
编辑://现在更改文件夹(打开或关闭)http://jsfiddle.net/8f3rL/35/
使用这个表,包括所有CRUD操作和用户友好的缩进:-
如何使用Angularjs-1和bootstral html表显示树数据结构?
treeDS.html
<!doctype html>
<html>
<head>
<title>Testbook: Admin App</title>
<link rel="stylesheet" type="text/css" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<style>
.level0{
text-indent : 0px;
color : #428bca;
}
.level1{
text-indent : 20px;
color : #428bca;
}
.level2{
text-indent : 40px;
color : #428bca;
}
.level3{
text-indent : 60px;
color : #428bca;
}
.level4{
text-indent : 80px;
color : #428bca;
}
.level5{
text-indent : 100px;
color : #428bca;
}
.level6{
text-indent : 120px;
color : #428bca;
}
.hasDropdown{
color : #428bca ;
}
.noDropdown{
color : #000000;
}
div.tooltip-inner {
text-align: center;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
margin-bottom: 6px;
background-color: #505050;
font-size: 14px;
}
</style>
</head>
<body ng-app="treeDataStructureApp" ng-controller="treeDataStructureCtrl">
<div class="container-fluid" style="padding-left : 25px;">
<br><br><br>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<span class="label label-default ng-binding" style="font-size : 25px">
Tree Data Structure Implementation Using Bootstrap Table
</span>
</div>
</div>
<br><br><br>
<div class="row">
<div class="col-md-3">
<button ng-click="addNewNodeAtRootLevel()" type="button" class="btn btn-primary btn-sm">Add New Node</button>
</div>
</div>
<br>
<div class="row">
<div class="col-md-12">
<table class="table table-hover table-bordered" id="mytable" style="width: 90%;">
<caption></caption>
<thead>
<tr class="info">
<th
data-toggle="tooltip" data-placement="top" title="click here to expand/close"
ng-click="expandAll()">
Name
<span ng-if="!showAll" class="glyphicon glyphicon-triangle-right"
aria-hidden="true"
data-toggle="tooltip" data-placement="top" title="Help: expand all nodes">
</span>
<span ng-if="showAll" class="glyphicon glyphicon-triangle-bottom"
aria-hidden="true"
data-toggle="tooltip" data-placement="top" title="Help: ">
</span>
</th>
<th>Id</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="node in nodesTableArr | filter : {isShow : true }" ng-class=" colorBackgroundOfNewnode(node)" >
<td ng-class="[hasDropdown(node), selectIndentationClass(node)]">
<span ng-model="node.editable" contenteditable='node.isEditable' ng-click="toggleDropdown(node)"> {{node.name}}</span>
</td>
<td contenteditable='false'> {{node.id}} </td>
<td contenteditable='false'>
<span ng-click="addChildNode(node)" class="glyphicon glyphicon-plus" aria-hidden="true"
data-toggle="tooltip" data-placement="top" title="Help: add new node under this node edit its name and press save button,save button will show after editing its name">
</span>
<span ng-click="deleteNode(node, 'concept')" class="glyphicon glyphicon-minus"
aria-hidden="true"
data-toggle="tooltip" data-placement="top" title="Help: delete this node, all nodes under it will also be deleted">
</span>
<span ng-click="editNode(node)" class="glyphicon glyphicon-edit"
aria-hidden="true"
data-toggle="tooltip" data-placement="top" title="Help: edit name and then press update button, update button will show, after editing its name">
</span>
<button ng-click="saveNewNodeCB (node, false)" type="button"
class="btn btn-primary btn-xs" ng-show="node.isSaveBtn">save
</button>
<button ng-click="updateNode(node)" type="button" class="btn btn-primary btn-xs"
ng-show="node.isUpdateBtn">update
</button>
<span ng-medel="operationStatusMessage" ng-show="node.isShowMessage">
<small>{{operationStatusMessage}} </small>
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-route.min.js" type="text/javascript"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.1.js" type="text/javascript"></script>
<script src="treeDS.js" type="text/javascript"></script>
</body>
treeDS.js文件
/* **由Aditya于2015年10月15日创建。*/使用严格的;
var app = angular.module('treeDataStructureApp',[]);app.controller('treeDataStructureCtrl', ['$scope',function ($scope){
// add new node at top level here
$scope.isAddExamNode = false;
$scope.addNewNodeAtRootLevel = function(){
$scope.isAddExamNode = true;
var newNode = {
name: "new node",
id : "",
level: 0,
parent: "root",
toggleStatus : false,
parentId : -1,
isShow: true,
isEditable : false,
childCount: 0,
isSaveBtn : false,
isShowMessage : false,
type : "exam"
};
$scope.nodesTableArr.unshift(newNode);
};
// add new node.
$scope.operationStatusMessage = "";
$scope.currentNodeSelected = {};
var uniqueIdForNewNodes = 0;
$scope.addChildNode = function(node){
// add row to table.
$scope.operationStatusMessage = "";
$scope.currentNodeSelected = node;
for (var i = 0; i < $scope.nodesTableArr.length; i++) {
if($scope.nodesTableArr[i].id == node.id){
$scope.nodesTableArr.splice(i + 1, 0, {
name: "new node",
id : uniqueIdForNewNodes,
level: node.level + 1,
parent: node.name,
toggleStatus : false,
parentId : node.id,
isShow: true,
isEditable : false,
childCount: 0,
isSaveBtn : false,
isShowMessage : false,
type : "nonExam"
});
break;
}
}
uniqueIdForNewNodes += 1;
};
$scope.saveNewNode = function(node, isExamNode){
alert("You can send request on server to add this node here.");
$scope.saveNewNodeCB();
};
$scope.saveNewNodeCB = function(){
$scope.resetOperationStatusMessage();
$scope.operationStatusMessage = "node Saved Successfully";
$scope.currentNodeSelected.isShowMessage = true;
$scope.currentNodeSelected.isSaveBtn = false;
// update node id in newly added node object, so that if we add new node under it, it has its valid parent id.
for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
var node = $scope.nodesTableArr[i];
if(node == $scope.conceptNodeToAdd)
node.id = response.data.node;
}
alert("send request to server here to save this node.");
};
$scope.editNode = function(node){
$scope.nodeNameInOperation = node.name;
$scope.operationStatusMessage = "";
$scope.currentNodeSelected = node;
var nodeName = prompt("Please enter New node Name", node.name);
if(nodeName != "" && nodeName != null && node.name != undefined && nodeName != node.name){
node.name = nodeName;
if(node.id != ""){
node.isUpdateBtn = true;
}
else{
node.isSaveBtn = true;
}
}
};
$scope.updateNode = function(node){
alert("You can send request on server to update this node.");
$scope.updateNodeCB();
};
$scope.updateNodeCB = function(response){
$scope.resetOperationStatusMessage();
if(true){
$scope.currentNodeSelected.isShowMessage = true;
$scope.operationStatusMessage = "node Updated Successfully";
$scope.currentNodeSelected.isUpdateBtn = false;
}
};
// nodeType = concept/nonConcept
$scope.nodeToDelete = {};
$scope.deleteNode = function(node, nodeType){
$scope.nodeNameInOperation = node.name;
$scope.nodeTypeForMessage = nodeType;
$scope.nodeToDelete = node;
$scope.operationStatusMessage = "";
$scope.currentNodeSelected = node;
var message;
if(node.id == ""){
for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
if($scope.nodesTableArr[i] == $scope.currentNodeSelected)
$scope.nodesTableArr.splice(i, 1);
}
return 0 ;
}
var r = confirm("Warning! Be Carefull! On deletion all nodes under this node will be deleted.'nPress ok to delete node");
if (r == true) {
$scope.deleteNodeCB();
message = "nodes deleted successfully.";
} else {
message = "process cancelled.";
}
$scope.curPageNo = 1;
};
$scope.deleteNodeCB = function(){
$scope.resetOperationStatusMessage();
$scope.operationStatusMessage = "node deleted Successfully";
$scope.currentNodeSelected.isShowMessage = true;
for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
if($scope.nodesTableArr[i] == $scope.currentNodeSelected)
$scope.nodesTableArr.splice(i, 1);
}
};
$scope.resetOperationStatusMessage = function(){
for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
$scope.nodesTableArr[i].isShowMessage = false;
}
};
// concept nodes related operations ends here
var node = "";
$scope.nodesTableArr = [];
$scope.initializeNodeTreeTable = function(pChildArr){
var length = pChildArr.length || 0;
for(var i = 0 ; i < length ; i++){
var exam = pChildArr[i];
var level = 0;
var childCount = 0;
if(exam.children && exam.children.length)
childCount = exam.children.length;
$scope.nodesTableArr.push({name : exam.text, id : exam._id, parent : "root", toggleStatus : false,
parentId : -1, isShow : true, isEditable : false, level : 0, childCount : childCount,
isSaveBtn : false, isUpdateBtn : false
});
if(exam.children != undefined)
$scope.initializeNodeTreeTableHelper(exam.children, exam.text, exam._id, level);
}
};
$scope.initializeNodeTreeTableHelper = function(pChildArr, pParentName, pPparentId, pLevel){
var isShowNode = false;
pLevel = pLevel + 1 ;
for(var i = 0 ; i < pChildArr.length ; i++){
var node = pChildArr[i];
var childCount = node.children != undefined ? node.children.length : 0
$scope.nodesTableArr.push({name : node.text, id : node._id, parent : pParentName, toggleStatus : false,
parentId : pPparentId, isShow : isShowNode, isEditable : false, level : pLevel, childCount : childCount,
isSaveBtn : false, isUpdateBtn : false
});
if(node.children != undefined)
$scope.initializeNodeTreeTableHelper(node.children, node.text, node._id, pLevel)
}
};
$scope.selectedExam = "";
$scope.renderNodeTreeForExam = "selectedExamNode";
$scope.renderNodeTreeForExam = function(exam){
$scope.nodesTableArr = [];
$scope.selectedExam = exam;
var selectedExamArr = [exam];
if($scope.selectedExam == "allExams")
selectedExamArr = $scope.allExams
$scope.getAllNodes(selectedExamArr);
};
// view related functions.
$scope.selectIndentationClass = function(node){
return 'level' + node.level;
};
$scope.hasDropdown = function(node){
if(node.childCount > 0)
return "hasDropdown";
else
return "noDropdown";
};
$scope.colorBackgroundOfNewNode = function(node){
if(node.id == ""){
return "success";
}
};
$scope.toggleStatus = false;
$scope.toggleDropdown = function(node){
node.toggleStatus = node.toggleStatus == true ? false : true;
$scope.toggleStatus = node.toggleStatus;
$scope.toggleDropdownHelper(node.id, $scope.toggleStatus );
};
$scope.toggleDropdownHelper = function(parentNodeId, toggleStatus ){
for(var i = 0 ; i < $scope.nodesTableArr.length ; i++) {
node = $scope.nodesTableArr[i];
if(node.parentId == parentNodeId) {
if(toggleStatus == false)
$scope.toggleDropdownHelper(node.id, toggleStatus);
$scope.nodesTableArr[i].isShow = toggleStatus;
}
}
};
$scope.showAll = false;
$scope.expandAll = function(){
var i = 0;
$scope.showAll = $scope.showAll == true ? false : true;
if($scope.showAll) {
for (i = 0; i < $scope.nodesTableArr.length; i++)
$scope.nodesTableArr[i]['isShow'] = true;
}
else {
for (i = 0; i < $scope.nodesTableArr.length; i++)
if($scope.nodesTableArr[i]['level'] != 0)
$scope.nodesTableArr[i]['isShow'] = false;
}
};
$scope.initializeNodeTreeTable(sampleData.data)
}]);
var sampleData = {
"data": [
{
"_id": "557569e82a39650f65425104",
"depth": 0,
"text": "SBI Clerk",
"exam": "SBI Clerk",
"children": [
{
"_id": "55c2dee72a3965432eaac6a7",
"depth": 1,
"text": "Quantitative Aptitude",
"exam": "SBI Clerk",
"children": [
{
"_id": "55c2dee72a3965432eaac6a8",
"depth": 2,
"text": "Simplification",
"exam": "SBI Clerk",
"children": [
{
"_id": "55c2dee72a3965432eaac6a9",
"depth": 3,
"text": "Bodmas Rule",
"exam": "SBI Clerk",
"type": "topic",
"par": "Bodmas Rule"
},
{
"_id": "55c2dee72a3965432eaac6aa",
"depth": 3,
"text": "Surds And Indices",
"exam": "SBI Clerk",
"type": "topic",
"par": "Surds And Indices"
},
{
"_id": "55c2dee82a3965432eaac6ab",
"depth": 3,
"text": "Approx Value",
"exam": "SBI Clerk",
"type": "topic",
"par": "Approx Value"
},
{
"_id": "55c2dee82a3965432eaac6ac",
"depth": 3,
"text": "Percennodee",
"exam": "SBI Clerk",
"type": "topic",
"par": "Percennodee"
}
],
"type": "chapter",
"par": "Simplification"
}
],
"type": "subject",
"par": "Quantitative Aptitude"
}
],
"type": "exam",
"par": ""
}
]
};
jsFiddle:工作示例
http://jsfiddle.net/Aditya199121/y0te91dm/1/- 可扩展的画布作为Google Maps Javascript API中的覆盖
- jQuery递归搜索类的父元素
- 如何为表构建可扩展的子行(jQuery/Javascript)
- 递归调用相同的函数
- 递归过程中的Returning(1)完成了什么
- 从包含在for循环中的递归返回值的正确方式
- 递归可防止函数在一行中被多次单击
- 递归函数内部的异步调用
- 两个递归函数之间的区别
- 从递归函数返回的未定义
- 需要创建可扩展的目录
- 递归函数中的范围
- 递归方法中的组合
- JavaScript递归函数中的错误
- 为每个帖子添加可扩展的文本框
- 可扩展的 Div,在 CSS 中具有过渡功能
- 我如何从递归 $.each 中的对象中删除元素
- 使用 JavaScript JQUERY 或 CSS 制作可扩展的顶部栏
- 如何在 ExpressJS 中创建可扩展的控制器
- AngularJS:可扩展的递归树表