I made a recursive ng-repeat element, and trying to manipulate things has turned into a nightmare, because I don't have reference to the parent I'm iterating over.
我做了一个递归的ng-repeat元素,试图操作事情已经变成了一场噩梦,因为我没有要遍历的父元素的引用。
The ng-repeat looks like this:
ng-repeat表示如下:
ng-repeat="(key, value) in value"
Remember It's recursive, so each value in value becomes the new value, so I can't just use the "in" value from ng-repeat. I want to do such things as checking if the parent is an array, but $parent is some weird thing, not the parent element of the current iteration value.
记住它是递归的,所以值中的每个值都变成了新的值,所以我不能只使用ng-repeat中的“in”值。我想检查父元素是否是数组,但是$parent是某种奇怪的东西,而不是当前迭代值的父元素。
Some examples of things I want to do is:
我想做的一些事情的例子是:
ng-show="isArray(parent)"
ng-click="delete(parent, $index)"
(as an example of what I'm doing as a work around, I've had to add an ___ISARRAYELEMENT___ property to each of my array elements, just to know that it's in an array >.>;;)
(作为我正在做的工作的一个例子,我必须向我的每个数组元素添加___ISARRAYELEMENT___属性,只需要知道它在一个数组>中。>;;)
EDIT: Basically I want to know if there is any convenient meta data in an ng-repeat context that I'm missing.
编辑:基本上,我想知道是否有任何方便的元数据,在一个ng-repeat上下文中,我错过了。
EDIT: Ok here is the html in it's entirety:
编辑:好的,这是完整的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>
One thing I would like to do is replace isArrayElement(value) with isArray(parent), because isArrayElement relies on meta data I added to the array, which I would prefer to not have to add.
我想做的一件事是用isArray(父)替换isArrayElement(值),因为isArrayElement依赖于我添加到数组中的元数据,我宁愿不添加它。
2 个解决方案
#1
28
ng-repeat
creates a new scope for each element.ng-include
also creates a new scope.
ng-repeat为每个元素创建一个新的范围。ng-include还创建了一个新的范围。
When you use ng-include
together with ng-repeat
, there are 2 scopes created for each element:
当您使用ng-include和ng-repeat时,为每个元素创建了两个作用域:
- Scope created by
ng-repeat
for current element. This scope holds the current element in the iteration. - 由ng-repeat创建的范围,用于当前元素。此范围保存迭代中的当前元素。
-
Child scope created by
ng-include
which inherits fromng-repeat
's created scope. - 由ng-include创建的子范围,它继承了ng-repeat创建的范围。
The $parent
property of current scope allows you to access its parent scope.
当前作用域的$parent属性允许您访问它的父作用域。
Essentially, scope created by ng-include
is empty, when you access value
and key
in your node.html
, it actually access the inherited values from parent scope created by ng-repeat
.
实际上,当您访问节点中的值和键时,ng-include创建的范围是空的。它实际*问了由ng-repeat创建的父作用域的继承值。
In your node.html, accessing {{value}}
is actually the same as {{$parent.value}}
. Therefore if you need to access the parent of the current element, you have to do one step further by accessing {{$parent.$parent.value}}
在你的节点。访问{{值}}的html实际上与{{$parent.value}相同。因此,如果您需要访问当前元素的父元素,则必须通过访问{{$parent.$parent. $parent.value}来更进一步。
This DEMO will clear things up:
这个演示将会澄清一些事情:
<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>
If you need to simplify the way to access the parent, you could try initializing the parent using onload
of ng-include
. Like this:
如果您需要简化访问父进程的方法,您可以尝试使用ng的onload初始化父进程。是这样的:
In your top level, there is no ng-if
=> only 2 level deep
在您的顶层,没有ng-if =>只有2级深
<ul>
<li ng-repeat="(key,value) in json"
ng-include="'node.html'" onload="parent=$parent.$parent"></li>
</ul>
In your sub levels, there is ng-if
=> 3 levels deep:
在您的子级别中,有ng-if => 3级深度:
<ul ng-if="isObject(value)">
<li ng-repeat="(key,value) in value"
ng-include="'node.html'" onload="parent=$parent.$parent.$parent"></li>
</ul>
Inside the template, you could access the parent using parent
, grandparent using parent.parent
and so on.
在模板中,可以使用父类访问父类,使用父类访问祖父类。父母等等。
演示
#2
3
I would stay away from Angular's $parent
and all the $scope
creation and inheritance madness. What you need is to keep a reference to the parent object, not finding how many scopes are in-between ng-include
's and ng-repeat
's and juggling with $parent.$parent
. My suggestion is to explicitly save references to the values you are interested in, just implement it yourself with custom logic. For example, if you want to expose a value from the parent ng-repeat to the child ng-repeat
我会远离角的$parent和所有的$scope创建和继承的疯狂。您需要的是保持对父对象的引用,而不是发现在ng-include和ng-repeat之间有多少作用域,以及与$parent的杂费。我的建议是显式地保存对您感兴趣的值的引用,只需使用自定义逻辑实现它。例如,如果您想要从父元素中公开一个值,请重复使用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>
Then in your javascript code you can access all parents recursively
然后在javascript代码中,你可以递归地访问所有的父母。
function doSomething(value){
parent1 = value._parent;
parent2 = parent1._parent;
}
Same code with ng-include
相同的代码与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>
#1
28
ng-repeat
creates a new scope for each element.ng-include
also creates a new scope.
ng-repeat为每个元素创建一个新的范围。ng-include还创建了一个新的范围。
When you use ng-include
together with ng-repeat
, there are 2 scopes created for each element:
当您使用ng-include和ng-repeat时,为每个元素创建了两个作用域:
- Scope created by
ng-repeat
for current element. This scope holds the current element in the iteration. - 由ng-repeat创建的范围,用于当前元素。此范围保存迭代中的当前元素。
-
Child scope created by
ng-include
which inherits fromng-repeat
's created scope. - 由ng-include创建的子范围,它继承了ng-repeat创建的范围。
The $parent
property of current scope allows you to access its parent scope.
当前作用域的$parent属性允许您访问它的父作用域。
Essentially, scope created by ng-include
is empty, when you access value
and key
in your node.html
, it actually access the inherited values from parent scope created by ng-repeat
.
实际上,当您访问节点中的值和键时,ng-include创建的范围是空的。它实际*问了由ng-repeat创建的父作用域的继承值。
In your node.html, accessing {{value}}
is actually the same as {{$parent.value}}
. Therefore if you need to access the parent of the current element, you have to do one step further by accessing {{$parent.$parent.value}}
在你的节点。访问{{值}}的html实际上与{{$parent.value}相同。因此,如果您需要访问当前元素的父元素,则必须通过访问{{$parent.$parent. $parent.value}来更进一步。
This DEMO will clear things up:
这个演示将会澄清一些事情:
<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>
If you need to simplify the way to access the parent, you could try initializing the parent using onload
of ng-include
. Like this:
如果您需要简化访问父进程的方法,您可以尝试使用ng的onload初始化父进程。是这样的:
In your top level, there is no ng-if
=> only 2 level deep
在您的顶层,没有ng-if =>只有2级深
<ul>
<li ng-repeat="(key,value) in json"
ng-include="'node.html'" onload="parent=$parent.$parent"></li>
</ul>
In your sub levels, there is ng-if
=> 3 levels deep:
在您的子级别中,有ng-if => 3级深度:
<ul ng-if="isObject(value)">
<li ng-repeat="(key,value) in value"
ng-include="'node.html'" onload="parent=$parent.$parent.$parent"></li>
</ul>
Inside the template, you could access the parent using parent
, grandparent using parent.parent
and so on.
在模板中,可以使用父类访问父类,使用父类访问祖父类。父母等等。
演示
#2
3
I would stay away from Angular's $parent
and all the $scope
creation and inheritance madness. What you need is to keep a reference to the parent object, not finding how many scopes are in-between ng-include
's and ng-repeat
's and juggling with $parent.$parent
. My suggestion is to explicitly save references to the values you are interested in, just implement it yourself with custom logic. For example, if you want to expose a value from the parent ng-repeat to the child ng-repeat
我会远离角的$parent和所有的$scope创建和继承的疯狂。您需要的是保持对父对象的引用,而不是发现在ng-include和ng-repeat之间有多少作用域,以及与$parent的杂费。我的建议是显式地保存对您感兴趣的值的引用,只需使用自定义逻辑实现它。例如,如果您想要从父元素中公开一个值,请重复使用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>
Then in your javascript code you can access all parents recursively
然后在javascript代码中,你可以递归地访问所有的父母。
function doSomething(value){
parent1 = value._parent;
parent2 = parent1._parent;
}
Same code with ng-include
相同的代码与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>