Hacking with Angular:如何在深层嵌套ngRepeat中获取不同层级的$index

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

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

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

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

现在有这么一个要求,我需要将上面的那个 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">
                        <ul class="list-group">
                            <li class="list-group-item" ng-repeat="v in item.books track by $index" ng-init="innerIndex = $index">
                                {{v.name}} <span class="inner-index">innerIndex:{{innerIndex}}</span><button class="btn btn-danger" ng-click="vm.removeItem(outerIndex, innerIndex)">删除</button>
                            </li>
                            <li class="list-group-item">
                                <form class="form-inline">
                                    <input class="form-control" ng-model="vm.tempItem[$index]" type="text">
                                    <button class="btn btn-primary" ng-click="vm.addItem(outerIndex)">添加一项</button>
                                </form>
                            </li>
                        </ul>

                    </li>
                    <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">
    <link rel="stylesheet" href="../lib/jsonFormater/jsonFormater.css">
    <script src="http://cdn.bootcss.com/jquery/2.0.0/jquery.js"></script>
    <script src="http://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.js"></script>
    <script src="../lib/jsonFormater/jsonFormater.js"></script>
    <script src="../../angular-1.4.5/angular.js"></script>
    <script src="app.js"></script>
    <style>
        .outer-index {
            color: #FF0000;
            background-color: #f8f8f8;
            padding: 3px;
            border-radius: 6px;
        }
        .inner-index {
            color: #00AA00;
            background-color: #f8f8f8;
            padding: 3px;
            border-radius: 6px;
        }
    </style>
</head>
<body>
    <div class="container-fluid" ng-controller="AppController as vm">
        <div class="row">
            <div class="col-md-6">
                <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">
                        <ul class="list-group">
                            <li class="list-group-item" ng-repeat="v in item.books track by $index" ng-init="innerIndex = $index">
                                {{v.name}} <span class="inner-index">innerIndex:{{innerIndex}}</span><button class="btn btn-danger" ng-click="vm.removeItem(outerIndex, innerIndex)">删除</button>
                            </li>
                            <li class="list-group-item">
                                <form class="form-inline">
                                    <input class="form-control" ng-model="vm.tempItem[$index]" type="text">
                                    <button class="btn btn-primary" ng-click="vm.addItem(outerIndex)">添加一项</button>
                                </form>
                            </li>
                        </ul>

                    </li>
                    <hr ng-show="!$last">
                </ul>
            </div>
            <div id="show-container" class="col-md-6">
                <h3>vm.appData:</h3>
                <div id="json-container"></div>
            </div>
        </div>
    </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'},
                    {name: 'nodejs'},
                    {name: 'react'}
                ]
            },
            {
                name: 'Java从入门到跑路',
                author: '呵呵哒',
                books: [
                    {name: '雪碧'},
                    {name: '百事可乐'},
                    {name: '鸡尾酒'}
                ]
            }
        ];

        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, 1);
            vm.jf.doFormat(vm.appData);
        }

        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);
            vm.jf.doFormat(vm.appData);
        }
    }
})();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值