How to get parent element inside ng-include when iterating in ng-repeat recursively

Jas*_*ell 12 javascript angularjs

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.

The ng-repeat looks like this:

ng-repeat="(key, value) in value"
Run Code Online (Sandbox Code Playgroud)

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.

Some examples of things I want to do is:

ng-show="isArray(parent)"
ng-click="delete(parent, $index)"
Run Code Online (Sandbox Code Playgroud)

(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 >.>;;)

EDIT: Basically I want to know if there is any convenient meta data in an ng-repeat context that I'm missing.

EDIT: Ok here is the html in it's entirety:

<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>
Run Code Online (Sandbox Code Playgroud)

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.

Kha*_* TO 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>
Run Code Online (Sandbox Code Playgroud)

如果您需要简化访问父级的方式,可以尝试使用onload的初始化父级ng-include.像这样:

在您的顶级,没有ng-if=>只有2级深

<ul>
    <li ng-repeat="(key,value) in json" 
     ng-include="'node.html'" onload="parent=$parent.$parent"></li>
</ul>
Run Code Online (Sandbox Code Playgroud)

在子级别中,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>
Run Code Online (Sandbox Code Playgroud)

在模板内部,您可以使用parent,祖父母使用parent.parent等访问父级.

DEMO