效果图:
新建一个html文件,将代码粘贴进去,打开浏览器就能看到效果
<!DOCTYPE html>
<html>
<head>
<meta name="description">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<meta charset="utf-8">
<title>angular.js递归树组件</title>
<script src="https://cdn.bootcdn.net/ajax/libs/angular.js/1.3.6/angular.js"></script>
</head>
<body>
<div ng-app="com.ngbook.demo">
<div ng-controller="DemoController as demo" class="container">
<div class="row">
<h1>angular.js递归树组件</h1>
</div>
<div class="row">
<tree-view tree-data="demo.tree" text-field="name" value-field='id'
item-clicked="demo.itemClicked($item)" item-checked-changed="demo.itemCheckedChanged($item)"
can-checked="true">
</tree-view>
</div>
<div class="row">
<h2>单选框选中的值</h2>
<pre>{{demo.selectedItem | json}}</pre>
</div>
<div class="row">
<h2>点击文本选中的值</h2>
<pre>{{demo.clickItem | json}}</pre>
</div>
<script type="text/ng-template" id="/treeView.html">
<ul class="tree-view">
<li ng-repeat="item in treeData" ng-include="itemTemplateUrl || '/treeItem.html'" ></li>
</ul>
</script>
<script type="text/ng-template" id="/treeItem.html">
<i ng-click="itemExpended(item, $event);" class="{{getItemIcon(item)}}"></i>
<input type="checkbox" ng-model="item.$$isChecked" class="check-box" ng-if="canChecked" ng-change="warpCallback('itemCheckedChanged', item, $event)">
<span class='text-field' ng-click="warpCallback('itemClicked', item, $event);">{{item[textField]}}</span>
<ul ng-if="!isLeaf(item)" ng-show="item.$$isExpend">
<li ng-repeat="item in item.children" ng-include="itemTemplateUrl || '/treeItem.html'"></li>
</ul>
</script>
</div>
</div>
</body>
</html>
<script>
angular.module("com.ngbook.demo", [])
.controller("DemoController", ['$http', function($http) {
var vm = this;
vm.tree = [{
"id": "1",
"pid": "0",
"name": "三国演义",
"children": [{
"id": "4",
"pid": "1",
"name": "曹操",
"children": [{
"id": "7",
"pid": "4",
"name": "后宫",
"children": [{
"id": "15",
"pid": "7",
"name": "小乔"
},
{
"id": "16",
"pid": "7",
"name": "大乔"
}
]
},
{
"id": "8",
"pid": "4",
"name": "曹植"
},
{
"id": "9",
"pid": "4",
"name": "曹冲"
},
{
"id": "10",
"pid": "4",
"name": "曹丕"
}
]
},
{
"id": "5",
"pid": "1",
"name": "刘备",
"children": [{
"id": "19",
"pid": "5",
"name": "张飞"
},
{
"id": "20",
"pid": "5",
"name": "赵子龙"
}
]
}
]
},
{
"id": "2",
"pid": "0",
"name": "水浒传",
"children": [{
"id": "13",
"pid": "2",
"name": "武松"
},
{
"id": "14",
"pid": "2",
"name": "林冲"
}
]
},
{
"id": "3",
"pid": "0",
"name": "西游记",
"children": [{
"id": "11",
"pid": "3",
"name": "孙悟空"
},
{
"id": "12",
"pid": "3",
"name": "猪八戒"
}
]
}
];
vm.selectedItem = {}
vm.clickItem = {}
vm.itemClicked = function($item) {
vm.clickItem = $item;
console.log($item, 'item clicked');
};
vm.itemCheckedChanged = function($item) {
vm.selectedItem = $item;
console.log($item, 'item checked');
};
return vm;
}])
.directive('treeView', [function() {
return {
restrict: 'E',
templateUrl: '/treeView.html',
scope: {
treeData: '=',
canChecked: '=',
textField: '@',
itemClicked: '&',
itemCheckedChanged: '&',
itemTemplateUrl: '@'
},
controller: ['$scope', function($scope) {
$scope.itemExpended = function(item, $event) {
item.$$isExpend = !item.$$isExpend;
$event.stopPropagation();
};
$scope.getItemIcon = function(item) {
var isLeaf = $scope.isLeaf(item);
if (isLeaf) {
return 'fa fa-leaf';
}
return item.$$isExpend ? 'fa fa-minus' : 'fa fa-plus';
};
$scope.isLeaf = function(item) {
return !item.children || !item.children.length;
};
$scope.warpCallback = function(callback, item, $event) {
($scope[callback] || angular.noop)({
$item: item,
$event: $event
});
};
}]
};
}]);
</script>