angularjs 使用directive实现tree
<!DOCTYPE html>
<html ng-app="com.ngbook.demo">
<head>
<meta name="description" content="ng trrview example">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<meta charset="utf-8">
<title>JS Bin</title>
<script src="http://greengerong.github.io/self/cdn/angular.js"></script>
</head>
<body >
<style>
.panel{
border:1px solid #d6e4f4;
background: #f7fbff;
margin-bottom:-1px;
}
.panel .panel-header{
cursor: pointer;
height:40px;
line-height: 40px;
padding:0 15px;
border-bottom:1px dotted #e5e5e5;
}
</style>
<div ng-controller="DemoController as demo" class="container">
<div class="row">
<h2>Tree view</h2>
<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>Item selected</h2>
<pre>{{demo.selectedItem | json}}</pre>
</div>
<script type="text/ng-template" id="/treeView.html">
<table
class="table table-bordered table-hover text-center table-outer">
<thead>
<tr>
<th class="text-center">菜单名称</th>
<th class="text-center">前端路由</th>
<th class="text-center">icon 地址</th>
<th class="text-center">状态</th>
<th class="text-center">菜单操作</th>
</tr>
</thead>
<tbody ng-repeat="data in treeData" ng-include="itemTemplateUrl || '/treeItem.html'" ng-init="data.expand = false" ng-init="data.func = false">
</tbody>
</table>
</script>
<script type="text/ng-template" id="/treeItem.html">
<tr>
<td class="text-left" ng-style="{'border-left':(data.parent&&data.parent.expand||data.expand)?'3px solid #8fbbee':''}">
<span style="display: inline-block;" ng-style="{'margin-left':(data.level-1)*10}"></span>
<span style="color:#4a90e2">{{data.chapter}}</span>
{{data.name}}
</td>
<td>{{data.route}}</td>
<td>{{data.icon}}</td>
<td>
<span class="badge-parent" ng-show="data.status==1">
<div class="green-badge badeg-style"></div>
<span class="text-green"> {{data.status}}</span>
</span>
<span class="badge-parent" ng-show="data.status==2">
<div class="red-badge badeg-style"></div>
<span class="text-red">{{data.status}}</span>
</span>
</td>
<td class="text-align-center btn-a">
<a href="javascript:void(0)" class="primary-border" ng-click="menuModal(3, data)">
添加子菜单
</a>
<span class="divider"></span>
<a href="javascript:void(0)" class="primary-border" ng-click="menuModal(2, data)">
修改
</a>
<span class="divider"></span>
<a href="javascript:void(0)" class="primary-border" ng-click="changeStatus(data)">
{{data.status==1?'停用':'启用'}}
</a>
<span class="divider"></span>
<a href="javascript:void(0)" class="primary-border" ng-click="data.func = !data.func; showFunction(data)">
功能<span *ngIf="data.functions">{{(data == selectedFunc)&&selectedFunc.isShowFunc?'-':'+'}}</span>
</a>
<span class="divider"></span>
<a href="javascript:void(0)" class="danger-border" ng-click="deleteMenu(data.id)">
删除
</a>
<span class="divider" ng-if="!!data.children"></span>
<a href="javascript:void(0)" class="primary-border"
style="height:100%;padding:0 10px;display: inline-block;"
ng-if="!!data.children"
ng-click="data.expand = !data.expand">
<b class="collapse-sign" ng-if="!data.expand"><em class="fa fa-angle-up"></em></b>
<b class="collapse-sign" ng-if="data.expand"><em class="fa fa-angle-down"></em></b>
</a>
</td>
</tr>
<tr ng-if="data.func">
<td colspan="6" style="padding:16px 6%!important;" class="func-td">
<table
class="functions table table-bordered table-hover text-center">
<thead>
<tr>
<th class="text-center">功能名称</th>
<th class="text-center">路由</th>
<th class="text-center">请求方式</th>
<th class="text-center">操作</th>
<th class="text-center">
<a href="javascript:void(0)" class="primary-border" ng-click="funcModal(1, data)">+添加功能</a>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="func in functions">
<td>
{{func.name}}
</td>
<td>{{func.route}}</td>
<td>{{func.method}}</td>
<td class="btn-group">
<a href="javascript:void(0)" class="primary-border" ng-click="funcModal(2, data, func)">修改</a>
<span class="divider"></span>
<a href="javascript:void(0)" class="danger-border" ng-click="deleteFunc(func.id)">删除</a>
</td>
<td></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr ng-if="data.expand">
<td colspan="5">
<table
class="table table-bordered table-hover text-center table-outer">
<thead>
<tr>
<th class="text-center">菜单名称</th>
<th class="text-center">前端路由</th>
<th class="text-center">icon 地址</th>
<th class="text-center">状态</th>
<th class="text-center">菜单操作</th>
</tr>
</thead>
<tbody ng-repeat="data in data.children" ng-include="itemTemplateUrl || '/treeItem.html'">
</tbody>
</table>
</td>
</tr>
<!-- <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>
</body>
</html>
<script>
angular.module("com.ngbook.demo", [])
.controller("DemoController", ['$http',function($http){
var vm = this;
vm.tree = [{
"id": 2,
"name": "站点管理",
"route": "#",
"icon": "icon-zhandian",
"method": "",
"status": 1,
"parentId": 0,
"level": 1,
"children": [{
"id": 16,
"name": "站点口令设置",
"route": "app.site.siteCommand",
"icon": "icon-zhongzhirenzhengkouling01",
"method": "",
"status": 1,
"parentId": 2,
"level": 2,
"children": [{
"id": 22,
"name": "站点口令设置",
"route": "app.site.siteCommand",
"icon": "icon-zhongzhirenzhengkouling01",
"method": "",
"status": 1,
"parentId": 16,
"level": 3,
"functions": [{
"id": 22,
"name": "查询所有站点",
"route": "/api/xxx",
"icon": "",
"method": "GET",
"status": 1,
"parentId": 22,
"level": 2
}]
}],
"functions": null
}, {
"id": 17,
"name": "下载链接管理",
"route": "app.site.url",
"icon": "icon-lianjie",
"method": "",
"status": 1,
"parentId": 2,
"level": 2,
"children": [{
"id": 211,
"name": "站点口令设置",
"route": "app.site.siteCommand",
"icon": "icon-zhongzhirenzhengkouling01",
"method": "",
"status": 1,
"parentId": 17,
"level": 3
}],
"functions": null
}],
"functions": [{
"id": 225,
"name": "查询所有站点",
"route": "/api/xxx",
"icon": "",
"method": "GET",
"status": 1,
"parentId": 2,
"level": 2,
"children": null,
"functions": null
}]
}, {
"id": 1,
"name": "站点管理",
"route": "#",
"icon": "icon-zhandian",
"method": "",
"status": 1,
"parentId": 0,
"level": 1,
"children": [{
"id": 23,
"name": "站点口令设置",
"route": "app.site.siteCommand",
"icon": "icon-zhongzhirenzhengkouling01",
"method": "",
"status": 1,
"parentId": 1,
"level": 2,
"children": null,
"functions": null
}, {
"id": 18,
"name": "下载链接管理",
"route": "app.site.url",
"icon": "icon-lianjie",
"method": "",
"status": 1,
"parentId": 1,
"level": 2,
"children": null,
"functions": null
}],
"functions": [{
"id": 226,
"name": "查询所有站点",
"route": "/api/xxx",
"icon": "",
"method": "get",
"status": 1,
"parentId": 1,
"level": 2,
"children": null,
"functions": null
}]
}]
vm.itemClicked = function ($item) {
vm.selectedItem = $item;
console.log($item, 'item clicked');
};
vm.itemCheckedChanged = function($item){
$http.post('/url', $item);
console.log($item,'item checked');
};
return vm;
}])
.directive('treeView',[function(){
return {
restrict: 'E',
templateUrl: '/treeView.html',
transclude: true,
scope: {
treeData: '=',
canChecked: '=',
showFunction:'&',
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
});
};
$scope.dataCache = '';
$scope.showFunction = function(item){
if( $scope.dataCache ){
$scope.dataCache.func = false;
}
$scope.dataCache = item;
$scope.selectedFunc= item;
item.isShowFunc = item.isShowFunc? !item.isShowFunc : true;
$scope.functions = item.functions || [];
}
}]
};
}]);
</script>