【问题标题】:Angularjs wrong $index after orderByorderBy后Angularjs错误的$index
【发布时间】:2013-04-13 16:21:34
【问题描述】:

我是 Angular.js 的新手,在排序数组和处理排序后的数据时遇到了一些问题。

我有一个包含项目的列表,并希望按“Store.storeName”对它进行排序,到目前为止它正在工作。但是在对数据进行排序后,我的删除功能不再起作用。我认为那是因为 $index 在排序后是错误的,所以错误的数据被删除了。

我该如何解决?在范围内而不是在视图中排序数据?该怎么做?

以下是一些相关代码:

在视图中:

<tr ng-repeat="item in items | orderBy:'Store.storeName'">
                <td><input class="toggle" type="checkbox" ng-model="item.Completed"></td>
                <td>{{item.Name}}</td>
                <td>{{item.Quantity}} Stk.</td>
                <td>{{item.Price || 0 | number:2}} €</td>                
                <td>{{item.Quantity*item.Price|| 0 | number:2}} €</td>
                <td>{{item.Store.storeName}}</td> 
                <td><a><img src="img/delete.png" ng-click="removeItem($index)">{{$index}}</a></td>
            </tr>

在我的控制器中我有这个删除功能,它应该删除特定的数据:

$scope.removeItem = function(index){
        $scope.items.splice(index,1);
    }

这在视图中订购之前效果很好。 如果缺少重要的东西,请现在告诉我。

谢谢!

【问题讨论】:

    标签: angularjs sorting indexing angularjs-orderby


    【解决方案1】:

    如果有人需要使用$index,您可以为排序/过滤后的数组命名:

    <tr ng-repeat="item in sortedItems = (items | orderBy:'Store.storeName') track by $index">
    

    看我的回答here

    【讨论】:

    • 我认为这个答案很好,如果缺乏细节的话。我认为 hmk 的意思是,一旦将过滤后的列表放在一边,如上所述,就可以使用索引(即“sortedItems[$index]”)来检索所需的条目。
    【解决方案2】:

    我开始学习角度并遇到类似的问题,根据@pkozlowski-opensource 的回答,我用类似的方法解决了它

    <a>
      <img src="img/delete.png" ng-click="removeItem(items.indexOf(item))">
      {{items.indexOf(item)}}
    </a> 
    

    【讨论】:

    • 这是最好的,而且非常简单,而不是创建自定义过滤器等。+1
    • 这不是正确的答案吗?这解决了我的问题
    【解决方案3】:

    试试这个:

    $scope.remove = function(subtask) {
    
        var idx = $scope.subtasks.indexOf(subtask),
            st = $scope.currentTask.subtasks[idx];
    
        // remove from DB
        SubTask.remove({'subtaskId': subtask.id});
    
        // remove from local array
        $scope.subtasks.splice(idx,1);
    
    }
    

    你可以在我的博客this entry找到详细的解释。

    【讨论】:

      【解决方案4】:

      我本来只想发表评论,但我没有“声誉”。

      mile 的解决方案也正是我所需要的。回答 pkozlowski.opensource 的问题:当您嵌套了 ngRepeats、动态列表(例如,您允许删除的地方)或两者(我的情况)时,使用 $index 不起作用,因为这将是错误的排序后的后端数据索引并使用ngInit 缓存值也不起作用,因为列表更改时不会重新评估它。

      请注意,mile 的解决方案允许通过传递参数&lt;tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'"&gt; 来自定义附加的索引属性名称

      我的调整版本:

      .filter( 'repeatIndex', function repeatIndex()
      {
      // This filter must be called AFTER 'filter'ing 
      //  and BEFORE 'orderBy' to be useful.
          return( function( array, index_name )
          {
              index_name = index_name || 'index';
              array.forEach( function( each, i )
              {each[ index_name ] = i;});
              return( array );
          });
      })
      

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题,并且该主题中的其他答案不适合我的情况。

        我已经用自定义过滤器解决了我的问题:

        angular.module('utils', []).filter('index', function () {
            return function (array, index) {
                if (!index)
                    index = 'index';
                for (var i = 0; i < array.length; ++i) {
                    array[i][index] = i;
                }
                return array;
            };
        });
        

        可以这样使用:

        <tr ng-repeat="item in items | index | orderBy:'Store.storeName'">
        

        然后在 HTML 中,您可以使用 item.index 而不是 $index

        此方法适用于对象的集合。

        请注意,此自定义过滤器应该是应用的所有过滤器列表中的第一个(orderBy 等),它会将附加属性 index(名称可自定义)添加到每个对象集合。

        【讨论】:

        • 您能否详细说明为什么其他答案不适合您的情况?
        • @pkozlowski.opensource 这要干净得多。还取决于可以附加哪些事件,以及 indexOf 中项目的复杂性要高效得多。此外,$scope.items.splice($scope.items.indexOf(item),1); 对于重复项也不会按预期工作。
        • @martin 你应该用实数来支持你关于性能的声明。过滤器在每个 $digest 循环中执行的巨大 缺点,所以我认为它对性能没有帮助...
        • @pkozlowski.opensource 确实如此,每个 $digest 循环运行两次。重要的是“取决于可以附加的事件”,当您无法控制速率时,性能很重要,例如,不受限制的滚动事件 - 我知道的极端情况。
        • @mile 好吧,我确实有重复,这就是我想要的,只是有点遗憾 Angular 没有跟踪 $ 变量中的原始索引或原始索引。我试过(key, item) in items,它也不起作用。 (密钥未保持原样)
        【解决方案6】:

        取而代之的是,或者在 $index 上进行中继 - 正如您已经注意到的那样 - 将指向已排序/过滤数组中的索引,您可以将项目本身传递给您的 removeItem 函数:

        <a><img src="img/delete.png" ng-click="removeItem(item)">{{$index}}</a>
        

        修改removeItem函数,使用数组的indexOf方法查找索引,如下:

        $scope.removeItem = function(item){
           $scope.items.splice($scope.items.indexOf(item),1);
        }
        

        【讨论】:

        • @pkozlowski.opensource 你是个天才!你可以传递一个项目,而不是索引..哇!!谢谢大佬。
        • 数组 indexOf 在 Internet Explorer 8 及更低版本中不可用。
        • 问题标题是在 orderBy 之后询问错误的 $index,这个答案没有解决。在某些情况下,您需要正确的 $index 值(例如列表上的 shift select)。应用 orderBy 过滤器后如何获得正确的 $index 值?
        • 您还可以通过执行以下操作从模板中的有序列表创建一个新数组:“ele in ordered_array = (array | filter: filter | orderBy: order_by)”
        • 整洁!谢谢兄弟。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-05
        相关资源
        最近更新 更多