Javascript 带ng重复的递归
在一个基于付费网站主题的Angular应用程序中,我的侧菜单中的项目具有以下数据结构。数据结构是我自己的,菜单是从原始菜单视图派生的,所有项目都在Javascript 带ng重复的递归,javascript,angularjs,recursion,angularjs-ng-repeat,Javascript,Angularjs,Recursion,Angularjs Ng Repeat,在一个基于付费网站主题的Angular应用程序中,我的侧菜单中的项目具有以下数据结构。数据结构是我自己的,菜单是从原始菜单视图派生的,所有项目都在ul硬编码中 在SidebarController.js中: $scope.menuItems = [ { "isNavItem": true, "href": "#/dashboard.html", "text": "Dashboard" }, { "isNavI
ul
硬编码中
在SidebarController.js
中:
$scope.menuItems = [
{
"isNavItem": true,
"href": "#/dashboard.html",
"text": "Dashboard"
},
{
"isNavItem": true,
"href": "javascript:;",
"text": "AngularJS Features",
"subItems": [
{
"href": "#/ui_bootstrap.html",
"text": " UI Bootstrap"
},
...
]
},
{
"isNavItem": true,
"href": "javascript:;",
"text": "jQuery Plugins",
"subItems": [
{
"href": "#/form-tools",
"text": " Form Tools"
},
{
"isNavItem": true,
"href": "javascript:;",
"text": " Datatables",
"subItems": [
{
"href": "#/datatables/managed.html",
"text": " Managed Datatables"
},
...
]
}
]
}
];
然后,我将以下局部视图绑定到该模型,如下所示:
<ul class="page-sidebar-menu" data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200" ng-class="{'page-sidebar-menu-closed': settings.layout.pageSidebarClosed}">
<li ng-repeat="item in menuItems" ng-class="{'start': item.isStart, 'nav-item': item.isNavItem}">
<a href="{{item.href}}" ng-class="{'nav-link nav-toggle': item.subItems && item.subItems.length > 0}">
<span class="title">{{item.text}}</span>
</a>
<ul ng-if="item.subItems && item.subItems.length > 0" class="sub-menu">
<li ng-repeat="item in item.subItems" ng-class="{'start': item.isStart, 'nav-item': item.isNavItem}">
<a href="{{item.href}}" ng-class="{'nav-link nav-toggle': item.subItems && item.subItems.length > 0}">
<span class="title">{{item.text}}</span>
</a>
</li>
</ul>
</li>
</ul>
-
-
注意在模型中看不到的视图绑定中可能有$scope
属性,反之亦然,但这是因为为了简洁起见,我对它们进行了编辑。
现在,由于第二级li
不包含其自身子项的条件ul
,因此不会呈现Datatable
菜单项下的子项
如何创建递归绑定到模型的视图或模板(或两者),以便呈现所有子项的所有子项?这通常最多只有四个级别。您可以简单地使用ng include生成分部并递归调用它:
部分应该是这样的:
<ul>
<li ng-repeat="item in item.subItems">
<a href="{{item.href}}" ng-class="{'nav-link nav-toggle': item.subItems && item.subItems.length > 0}">
<span class="title">{{item.text}}</span>
</a>
<div ng-switch on="item.subItems.length > 0">
<div ng-switch-when="true">
<div ng-init="subItems = item.subItems;" ng-include="'partialSubItems.html'"></div>
</div>
</div>
</li>
</ul>
-
以及您的html:
<ul class="page-sidebar-menu" data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200" ng-class="{'page-sidebar-menu-closed': settings.layout.pageSidebarClosed}">
<li ng-repeat="item in menuItems" ng-class="{'start': item.isStart, 'nav-item': item.isNavItem}">
<a href="{{item.href}}" ng-class="{'nav-link nav-toggle': item.subItems && item.subItems.length > 0}">
<span class="title">{{item.text}}</span>
</a>
<ul ng-if="item.subItems && item.subItems.length > 0" class="sub-menu">
<li ng-repeat="item in item.subItems" ng-class="{'start': item.isStart, 'nav-item': item.isNavItem}">
<a href="{{item.href}}" ng-class="{'nav-link nav-toggle': item.subItems && item.subItems.length > 0}">
<span class="title">{{item.text}}</span>
</a>
<div ng-switch on="item.subItems.length > 0">
<div ng-switch-when="true">
<div ng-init="subItems = item.subItems;" ng-include="'newpartial.html'"></div>
</div>
</div>
</li>
</ul>
</li>
</ul>
-
-
这是正在工作的plunker
如果您的意图是绘制一个子项级别不确定的菜单,那么一个好的实现可能是生成一个指令
有了指令,你就可以对菜单进行更多的控制
我创建了一个带有完整递归的基本exepmle,在上,您可以在同一页面上看到多个菜单的简单实现,在其中一个菜单上可以看到多个级别,请参见此
代码:
.directive('myMenu', ['$parse', function($parse) {
return {
restrict: 'A',
scope: true,
template:
'<li ng-repeat="item in List" ' +
'ng-class="{\'start\': item.isStart, \'nav-item\': item.isNavItem}">' +
'<a href="{{item.href}}" ng-class="{\'nav-link nav-toggle\': item.subItems && item.subItems.length > 0}">'+
'<span class="title"> {{item.text}}</span> ' +
'</a>'+
'<ul my-menu="item.subItems" class="sub-menu"> </ul>' +
'</li>',
link: function(scope,element,attrs){
//this List will be scope invariant so if you do multiple directive
//menus all of them wil now what list to use
scope.List = $parse(attrs.myMenu)(scope);
}
}
}])
<ul class="page-sidebar-menu"
data-keep-expanded="false"
data-auto-scroll="true"
data-slide-speed="200"
ng-class="{'page-sidebar-menu-closed': settings.layout.pageSidebarClosed}"
my-menu="menuItems">
</ul>
激光源角波导
编辑
正如Mathew Berg所建议的那样,如果子项列表为空,那么如果不想包含ul元素,那么可以将ul更改为类似的形式,例如,Rahul Arora的答案很好,请参见下面的类似示例。我要做的一个改变是使用组件而不是ng include。有关示例,请参见:
app
.component('recursiveItem'{
绑定:{
item:“您只需包含一个javascript模板和使用ng include的模板include就可以实现这一点
定义javascript模板
<script type="text/ng-template" id="menu.html">...</script>
。。。
包括:
<div ng-if="item.subItems.length" ng-include="'menu.html'"></div>
示例:在这个示例中,我使用了基本html,没有任何类,您可以根据需要使用这些类。我只是展示了基本的递归结构
在html中:
<ul>
<li ng-repeat="item in menuItems">
<a href="{{item.href}}">
<span>{{item.text}}</span>
</a>
<div ng-if="item.subItems.length" ng-include="'menu.html'"></div>
</li>
</ul>
<script type="text/ng-template" id="menu.html">
<ul>
<li ng-repeat="item in item.subItems">
<a href="{{item.href}}">
<span>{{item.text}}</span>
</a>
<div ng-if="item.subItems.length" ng-include="'menu.html'"></div>
</li>
</ul>
</script>
-
-
为了在angularJS中进行递归,我希望使用angularJS的基本功能和I.e指令
index.html
<rec-menu menu-items="menuItems"></rec-menu>
recMenu.html
<ul>
<li ng-repeat="item in $ctrl.menuItems">
<a ng-href="{{item.href}}">
<span ng-bind="item.text"></span>
</a>
<div ng-if="item.menuItems && item.menuItems.length">
<rec-menu menu-items="item.menuItems"></rec-menu>
</div>
</li>
</ul>
-
recMenu.html
angular.module('myApp').component('recMenu', {
templateUrl: 'recMenu.html',
bindings: {
menuItems: '<'
}
});
angular.module('myApp')。组件('recMenu'{
templateUrl:'recMenu.html',
绑定:{
MENUTION: '在使用带有<代码> NG的模板之前,包含或编写您自己的指令,我建议您考虑使用现有的树组件实现。
原因是,根据您的描述,这正是您所需要的。您有一个层次结构的树状数据结构,您希望显示它。我听上去很明显,您需要一个树状组件
请看一下以下实现(首选第一种):
以上所有操作只需要对模型进行轻微调整,或者使用代理模型
如果您坚持自己实现它(无论您最终如何实现它,基本上您仍将从头开始实现树组件),我建议您采用前面答案中提出的指导方法。我将这样做:
JS
var-app=angular.module('MyApp',[]);
app.controller('MyCtrl',函数($scope,$window){
$scope.menuItems=[
{
“isNavItem”:正确,
“href”:“#/dashboard.html”,
“文本”:“仪表板”
},
{
“isNavItem”:正确,
“href”:“javascript:;”,
“文本”:“AngularJS功能”,
“分项”:[
{
“href”:“#/ui_bootstrap.html”,
“文本”:“UI引导”
}
]
},
{
“isNavItem”:正确,
“人力资源
<ul>
<li ng-repeat="item in $ctrl.menuItems">
<a ng-href="{{item.href}}">
<span ng-bind="item.text"></span>
</a>
<div ng-if="item.menuItems && item.menuItems.length">
<rec-menu menu-items="item.menuItems"></rec-menu>
</div>
</li>
</ul>
angular.module('myApp').component('recMenu', {
templateUrl: 'recMenu.html',
bindings: {
menuItems: '<'
}
});
var app=angular.module('MyApp', []);
app.controller('MyCtrl', function($scope, $window) {
$scope.menuItems = [
{
"isNavItem": true,
"href": "#/dashboard.html",
"text": "Dashboard"
},
{
"isNavItem": true,
"href": "javascript:;",
"text": "AngularJS Features",
"subItems": [
{
"href": "#/ui_bootstrap.html",
"text": " UI Bootstrap"
}
]
},
{
"isNavItem": true,
"href": "javascript:;",
"text": "jQuery Plugins",
"subItems": [
{
"href": "#/form-tools",
"text": " Form Tools"
},
{
"isNavItem": true,
"href": "javascript:;",
"text": " Datatables",
"subItems": [
{
"href": "#/datatables/managed.html",
"text": " Managed Datatables"
}
]
}
]
}];
});
app.directive('myMenu', ['$compile', function($compile) {
return {
restrict: 'E',
scope: {
menu: '='
},
replace: true,
link: function(scope, elem, attrs) {
var items = $compile('<my-menu-item ng-repeat="item in menu" menu-item="item"></my-menu-item>')(scope);
elem.append(items);
},
template: '<ul class="page-sidebar-menu" data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200" ng-class="{\'page-sidebar-menu-closed\': settings.layout.pageSidebarClosed}"></ul>'
};
}]);
app.directive('myMenuItem', [function() {
return {
restrict: 'E',
scope: {
menuItem: '='
},
replace: true,
template: '<li ng-class="{\'start\': item.isStart, \'nav-item\': item.isNavItem}"><a href="{{menuItem.href}}" ng-class="{\'nav-link nav-toggle\': menuItem.subItems && menuItem.subItems.length > 0}"> <span class="title">{{menuItem.text}}</span></a><my-menu menu="menuItem.subItems"></my-menu></li>'
};
}]);
<div ng-app="MyApp" ng-controller="MyCtrl">
<my-menu menu="menuItems"></my-menu>
</div>
<script type="text/ng-template" id="tree_item_renderer.html">
{{data.name}}
<button ng-click="add(data)">Add node</button>
<button ng-click="delete(data)" ng-show="data.nodes.length > 0">Delete nodes</button>
<ul>
<li ng-repeat="data in data.nodes" ng-include="'tree_item_renderer.html'"></li>
</ul>
angular.module("myApp", []).
controller("TreeController", ['$scope', function($scope) {
$scope.delete = function(data) {
data.nodes = [];
};
$scope.add = function(data) {
var post = data.nodes.length + 1;
var newName = data.name + '-' + post;
data.nodes.push({name: newName,nodes: []});
};
$scope.tree = [{name: "Node", nodes: []}];
}]);
angular.module("myApp", []).controller("TreeController", ['$scope',function($scope) {
$scope.menuItems = [{
"isNavItem": true,
"href": "#/dashboard.html",
"text": "Dashboard"
}, {
"isNavItem": true,
"href": "javascript:;",
"text": "AngularJS Features",
"subItems": [{
"href": "#/ui_bootstrap.html",
"text": " UI Bootstrap"
}, {
"isNavItem": true,
"href": "javascript:;",
"text": "AngularJS Features",
"subItems": [{
"href": "#/ui_bootstrap.html",
"text": " UI Bootstrap"
}]
}]
}, {
"isNavItem": true,
"href": "javascript:;",
"text": "jQuery Plugins",
"subItems": [{
"href": "#/form-tools",
"text": " Form Tools"
}, {
"isNavItem": true,
"href": "javascript:;",
"text": " Datatables",
"subItems": [{
"href": "#/datatables/managed.html",
"text": " Managed Datatables"
}]
}]
}];
}]);
<script type="text/ng-template" id="tree_item_renderer.html">
<a href="{{item.href}}" ng-class="{'nav-link nav-toggle': item.subItems && item.subItems.length > 0}">
<span class="title">{{item.text}}</span>
</a>
<ul ng-if="item.subItems && item.subItems.length > 0" class="sub-menu">
<li ng-repeat="item in item.subItems" ng-class="{'start': item.isStart, 'nav-item': item.isNavItem}" ng-include="'tree_item_renderer.html'"></li>
</ul>
</script>
<div ng-app="myApp" ng-controller="TreeController">
<ul class="page-sidebar-menu" data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200" ng-class="{'page-sidebar-menu-closed': settings.layout.pageSidebarClosed}">
<li ng-repeat="item in menuItems" ng-class="{'start': item.isStart, 'nav-item': item.isNavItem}" ng-include="'tree_item_renderer.html'"></li>
</ul>
</div>
.directive('menuItem', function($compile){
return {
restrict: 'A',
scope: {
menuItem: '=menuItem'
},
templateUrl: 'menuItem.html',
replace: true,
link: function(scope, element){
var watcher = scope.$watch('menuItem.subItems', function(){
if(scope.menuItem.subItems && scope.menuItem.subItems.length){
var subMenuItems = angular.element('<ul><li ng-repeat="subItem in menuItem.subItems" menu-item="subItem"></li></ul>')
$compile(subMenuItems)(scope);
element.append(subMenuItems);
watcher();
}
});
}
}
})
<li>
<a ng-href="{{ menuItem.href }}">{{ menuItem.text }}</a>
</li>
<script type="text/ng-template" id="categoryTree">
{{ category.title }}
<ul ng-if="category.categories">
<li ng-repeat="category in category.categories" ng-include="'categoryTree'">
</li>
</ul>
</script>
<ul>
<li ng-repeat="category in categories" ng-include="'categoryTree'"></li>
</ul>