使用ngRepeat指令的时候,我们一般会通过$index获取当前层级的每一项循环的索引,但是当我们循环出来的数据中还有数组(数组A)需要我们循环的话,我们还是会使用ngRepeat来循环我们这个数组。但是这个时候,假如我们还需要数组A中的每一项的索引来做一些操作的话,这个时候我们就不能使用刚才的哪个$index,这个时候我们应该怎么办呢?这个时候就需要使用另外一个指令ngInit设置一个变量来保存我们每个循环的索引$index,这样就可以继续操作了,详细的过程参见下文。

在线的demo原文的链接angular-china

我们先来看一个数据对象,如下:

var appData = [
            {
                name: 'C++从入门到放弃',author: 'dreamapple',books: [
                    {name: 'github'},{name: 'google'},0)">'nodejs'},0)">'react'}
                ]
            },{
                name: 'Java从入门到跑路',0)">'呵呵哒',0)">'雪碧'},0)">'百事可乐'},0)">'鸡尾酒'}
                ]
            }
        ];

现在有这么一个要求,我需要将上面的那个appData循环出来,其中还要循环出来books里面的每一项,然后每一个books里面的每一项都可以进行删除,也可以给每一个books数组里面添加新的一项。

(1)循环出来这个appData数据还是很容易的,通过嵌套的ngRepeat很方便的就可以搞定了。

(2)关于嵌套我们能够使用的索引是$index,但是两层以上的话,如果每一层嵌套都使用$index作为索引的话,势必会引起混乱。这个时候就需要我们想一些办法去得到每一层的索引。

(3)我们目前比较好的一个做法就是通过ngInit指令,然后在循环开始的时候将每一层的索引保存在一个变量中,然后就可以在循环的不同层级之间使用了。

(4)我们还需要定义另一个数组vm.tempItem,这个数组也用于循环,循环出来的每一项用作被添加项的数据模型。

注意:循环books数组我们还有一些需要注意的地方,我们要使用track by语法,不然每次增加或者删除books里面的内容时,books每一项的$index不会发生变化,那么就不好进行删除操作了。

我把里面的重点部分单独拿了出来,然后大家一起来看一看:页面部分:

<ul class="list-group" ng-repeat="item in vm.appData" ng-init="outerIndex = $index"> <h3>{{item.name}}<span class="outer-index">outerIndex:{{outerIndex}}</span></h3> <h4>{{item.author}}</h4> <li class="list-group-item"> <"list-group"> <"list-group-item" ng-repeat="v in item.books track by $index" ng-init="innerIndex = $index"> {{v.name}} <"inner-index">innerIndex:{{innerIndex}}</span><button class="btn btn-danger" ng-click="vm.removeItem(outerIndex,innerIndex)">删除</button> </li> <form class="form-inline"> <input class="form-control" ng-model="vm.tempItem[$index]" type="text"> <"btn btn-primary" ng-click="vm.addItem(outerIndex)">添加一项</form> </li> </ul> </hr ng-show="!$last"> </ul>

控制器部分:

function removeItem(outerIndex,innerIndex) {
            vm.appData[outerIndex].books.splice(innerIndex,1);
        }

我们可以先看控制器里面的函数,removeItem这个函数有两个参数,一个是outerIndex,一个是innerIndex,其中outerIndex表示的是第一层循环的$index索引,innerIndex表示的是第二层的$index索引。每次删除一项我们都需要知道是删除第一层循环中哪一个对象中的哪一项。

在页面中我们通过ng-init="outerIndex = $index"保存了第一层循环的$index,通过使用ng-init="innerIndex = $index"保存了第二层循环的$index。所以接下来的操作都很方便了。

如果对我上面所说的还没有很好理解的话,你可以尝试自己练习一下。下面是源码部分:

HTML部分

head> <Meta charset="UTF-8"> <title>1</title> <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.css"> <"../lib/jsonFormater/jsonFormater.css"> <script src="http://cdn.bootcss.com/jquery/2.0.0/jquery.js"></script> <"http://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.js"></"../lib/jsonFormater/jsonFormater.js"></"../../angular-1.4.5/angular.js"></"app.js"></style> .outer-index { color: #FF0000; background-color: #f8f8f8; padding: 3px; border-radius: 6px; } .inner-index { #00AA00; 6px; } </style> </body> <div class="container-fluid" ng-controller="AppController as vm"> <"row"> <"col-md-6"> <{{item.name}}<{{outerIndex}}</{{item.author}}</{{v.name}} <{{innerIndex}}</div> <div id="show-container" class=h3>vm.appData:</"json-container"></div> </body>

JavaScript部分

(function() {
    angular.module('app',[])
    .controller('AppController',AppController);

    AppController.$inject = ['$scope'];

    function AppController($scope) {
        var vm = this;
        // 初始化原始数据
        var appData = [
            {
                name: 'C++从入门到放弃',author: 'dreamapple',books: [
                    {name: 'github'},{name: 'google'},96)">'nodejs'},96)">'react'}
                ]
            },{
                name: 'Java从入门到跑路',96)">'呵呵哒',96)">'雪碧'},96)">'百事可乐'},96)">'鸡尾酒'}
                ]
            }
        ];

        vm.appData = appData;
        vm.tempItem = [];
        vm.addItem = addItem;
        vm.removeItem = removeItem;

        config();

        function addItem(outerIndex) {
            if(vm.tempItem[outerIndex]) {
                vm.appData[outerIndex].books.push({
                    name: vm.tempItem[outerIndex]
                });
                vm.tempItem[outerIndex] = '';
                vm.jf.doFormat(vm.appData);
            }
            else {
                alert('添加项不能为空!')
            }
        }

        function removeItem(outerIndex,innerIndex) {
            vm.appData[outerIndex].books.splice(innerIndex,0)">1);
            vm.jf.doFormat(;
        }

        function config() {
            var options = {
                dom : '#json-container',tabSize: 2,quoteKeys: true,imgCollapsed: "../lib/jsonFormater/images/collapsed.gif",imgExpanded: "../lib/jsonFormater/images/expanded.gif",isCollapsible: true
            };
            vm.jf = new JsonFormater(options);
        }
    }
})();

Hacking with Angular:如何在深层嵌套ngRepeat中获取不同层级的$index的更多相关文章

  1. html5使用canvas实现弹幕功能示例

    这篇文章主要介绍了html5使用canvas实现弹幕功能示例的相关资料,需要的朋友可以参考下

  2. 前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)

    这篇文章主要介绍了前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. H5 canvas实现贪吃蛇小游戏

    本篇文章主要介绍了H5 canvas实现贪吃蛇小游戏,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. ios – parse.com用于键,预期字符串的无效类型,但是得到了数组

    我尝试将我的数据保存到parse.com.我已经预先在parse.com上创建了一个名为’SomeClass’的类.它有一个名为’mySpecialColumn’的列,其数据类型为String.这是我尝试使用以下代码保存数据的代码:如果我运行这个我得到:错误:密钥mySpecialColumn的无效类型,预期字符串,但得到数组这就是我在parse.com上的核心外观:有谁知道我为什么会收到这个错误?

  5. ios – 上下文类型’NSFastEnumeration’不能与数组文字一起使用

    斯威夫特3,你会这样做吗?解决方法正如您所发现的,您不能使用as-casting将数组文字的类型指定为NSFastEnumeration.您需要找到一个符合NSFastEnumeration的正确类,在您的情况下它是NSArray.通常写这样的东西:

  6. ios – 如何在swift3中增加String.Index?

    在swift2.3中运算符用于string.index增加例如.一世我改为swift3代码发生了“一元运算符”不能应用于’@valueString.Index’类型的操作数(又名’@lvalueString.CharacterView.Index’)“在swift3中我改写了例如.i=1但是这段代码无法解决.请帮我.解决方法String.Index是String.CharacterView.Ind

  7. ios – CoreData有序关系 – 使用NSFetchRequest批量取消

    或者,是否存在批量不支持的API,它不是私有的?解决方法目前我有一个解决方案,但不是一个干净的解决方案:我希望按照有序关系中的20个小组进行批量修改.所以,每次我索引一个索引,它的索引除以20,我为接下来的20使用新的NSFetchRequest,并通过调用公共字段名称来解除它们.

  8. ios – 获取资产目录文件夹中所有图像的数组

    在iOS中,是否可以获取资产目录文件夹中的图像数组?我不确定为什么会对此进行投票.我真的不知道从哪里开始.我的另一种方法是创建文件夹中所有文件的plist,但它似乎是多余的.我无法添加任何代码,因为我会添加什么?

  9. ios – Xcode只看到一些嵌套类的类似扩展,这些扩展是用不同的文件编写的

    解决方法我遇到过类似的问题,似乎编译器正在尝试处理扩展嵌套类的文件,在嵌套类定义之前.因此,您有此错误说该Space没有成员SomeClass.我发现的解决方案是转到目标设置,打开BuildPhases.在“编译源”部分中,您应该将用于定义嵌套类的文件放在扩展它的文件上.这个解决方案似乎甚至可以很好地与您的观察结果一致,当您重新创建文件时,它有时会编译,因为当您重新创建文件时,它在编译源中的位置会发生变化.

  10. ios – 来自调试器的消息:由于内存问题而终止

    我的应用程序使用Geojson文件.我使用MapBoxSDK将MGLpolyline添加到地图中.但问题是我的文件太大,以至于应用程序崩溃并收到错误:来自调试器的消息:由于内存问题而终止.我在第一次循环时面对66234个对象.我试图将数组块化为新数组,但没有成功.请帮我解决问题.这是我在地图上绘制的代码,这里是我的testprojectongithubuseXcode8.1如果有任何不同的第三方可

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部