我做了一个递归的ng-repeat元素,试图操纵事物已经变成了一场噩梦,因为我没有引用我正在迭代的父。
ng-repeat看起来像这样:
ng-repeat="(key, value) in value"
记住它是递归的,因此值中的每个值都成为新值,因此我不能只使用ng-repeat中的“in”值。我想做的事情是检查父项是否是一个数组,但是$ parent是一些奇怪的东西,而不是当前迭代值的父元素。
我想要做的事情的一些例子是:
ng-show="isArray(parent)"
ng-click="delete(parent, $index)"
(作为我正在做的工作的一个例子,我必须为我的每个数组元素添加一个___ISARRAYELEMENT___属性,只是为了知道它在数组中>。&gt ;;;)
编辑:基本上我想知道在我重复的ng-repeat上下文中是否有任何方便的元数据。
编辑:好的,这里是html的全部内容:
<html ng-app>
<head>
<title>JSON CRUD</title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<script src="angularjsoncrud.js"></script>
<script type="text/ng-template" id="node.html">
<button ng-click="minimized = !minimized" ng-show="!isLeaf(value)" ng-init="minimized=false" ng-class="{'glyphicon glyphicon-plus': minimized, 'glyphicon glyphicon-minus': !minimized}">-</button>
<input ng-model="value.___KEY___" ng-if="!isArrayElement(value)" />
<input ng-if="isLeaf(value)" ng-model="value.___VALUE___" />
<ul ng-if="!isLeaf(value)" ng-show="!minimized">
<li ng-repeat="(key,value) in value" ng-if="key != '___KEY___' && key != '___ISARRAY___'" ng-include="'node.html'"></li>
<button type="button" ng-if="isArray(value)" ng-click="addToArray(value)">Add Element</button>
</ul>
</script>
</head>
<body ng-app="Application" ng-controller="jsoncrudctrl">
<ul>
<li ng-repeat="(key,value) in json" ng-include="'node.html'"></li>
</ul>
<pre>{{stringify(json)}}</pre>
</body>
</html>
我想做的一件事是用isArray(parent)替换isArrayElement(value),因为isArrayElement依赖于我添加到数组的元数据,我宁愿不必添加。
答案 0 :(得分:29)
ng-repeat
为每个元素创建一个新范围
ng-include
也会创建一个新范围。
将ng-include
与ng-repeat
一起使用时,为每个元素创建了两个范围:
ng-repeat
为当前元素创建的范围。此范围保存迭代中的当前元素。ng-include
创建,从ng-repeat
创建的范围继承。 当前作用域的$parent
属性允许您访问其父作用域。
基本上,ng-include
创建的范围为空,当您访问value
中的key
和node.html
时,它实际上会访问 继承的值 来自ng-repeat
创建的父作用域。
在您的node.html中,访问{{value}}
实际上与{{$parent.value}}
相同。因此,如果您需要访问当前元素的父元素,则必须通过访问{{$parent.$parent.value}}
这DEMO会清除问题:
<script type="text/ng-template" id="node.html">
<div>
Current: key = {{key}}, value = {{value}}
</div>
<div>
Current (using $parent): key = {{$parent.key}}, value = {{$parent.value}}
</div>
<div>
Parent: key = {{$parent.$parent.key}}, value = {{$parent.$parent.value}}, isArray: {{isArray($parent.$parent.value)}}
</div>
<ul ng-if="isObject(value)"> //only iterate over object to avoid problems when iterating a string
<li ng-repeat="(key,value) in value" ng-include="'node.html'"></li>
</ul>
</script>
如果您需要简化访问父级的方式,可以尝试使用onload
的{{1}}初始化父级。像这样:
在您的顶级,没有ng-include
=&gt;只有2级深度
ng-if
在您的子级别中,有<ul>
<li ng-repeat="(key,value) in json"
ng-include="'node.html'" onload="parent=$parent.$parent"></li>
</ul>
=&gt; 3级深度:
ng-if
在模板内部,您可以使用 <ul ng-if="isObject(value)">
<li ng-repeat="(key,value) in value"
ng-include="'node.html'" onload="parent=$parent.$parent.$parent"></li>
</ul>
访问父级,使用parent
访问祖父母,依此类推。
答案 1 :(得分:3)
我会远离Angular的$parent
和所有$scope
创造和继承的疯狂。你需要的是保持对父对象的引用,而不是找到ng-include
和ng-repeat
之间有多少作用域,并且与$parent.$parent
玩杂耍。我的建议是显式保存引用到你感兴趣的值,只需用自定义逻辑自己实现它。例如,如果要将父ng-repeat中的值公开给子ng-repeat
<!-- Explictly save the value into the parent var -->
<div ng-init="parent = value">
<!-- Save parent reference and
update the parent var to point to the new value -->
<div ng-repeat="(k,value) in value"
ng-init="value._parent = parent; parent = value;">
<div ng-repeat="(k,value) in value"
ng-init="value._parent = parent">
<button ng-click="doSomething(value)"></button>
</div>
</div>
</div>
然后在您的javascript代码中,您可以递归访问所有父母
function doSomething(value){
parent1 = value._parent;
parent2 = parent1._parent;
}
与ng-include
<div ng-init="parent = value">
<div ng-repeat="(key,value) in value"
ng-init="value._parent = parent; parent = value;"
ng-include="'node.html'">
</div>
</div>
<script type="text/ng-template" id="node.html">
<div ng-if="!isLeaf(value)"
ng-repeat="(key,value) in value"
ng-init="value._parent = parent; parent = value;"
ng-include="'node.html'">
<button ng-if="isLeaf(value)" ng-click="doSomething(value)"></button>
</script>