【问题标题】:Angular.js more complex conditional loopsAngular.js 更复杂的条件循环
【发布时间】:2013-04-03 07:38:12
【问题描述】:

目标是创建这个

<h3>11.4.2013</h3>
<ul>
 <li>entry 1</li>
 <li>entry 2</li> 
 <li>entry 3</li>
</ul>

<h3>10.4.2013</h3>
<ul>
 <li>entry 4</li>
 <li>entry 5</li> 
 <li>entry 6</li>
</ul>

从这里

[
    {
        "name": "entry1",
        "date": "11.4.2013"
    },
    {
        "name": "entry2",
        "date": "11.4.2013"
    },
    {
        "name": "entry3",
        "date": "11.4.2013"
    },
    {
        "name": "entry4",
        "date": "10.4.2013"
    },
    {
        "name": "entry5",
        "date": "10.4.2013"
    },
    {
        "name": "entry6",
        "date": "10.4.2013"
    }
]

问题是 ng-repeat 必须在 li 上,所以我永远无法使用 ng-repeat 来做到这一点,对吗?我从 Mark Rajnoc 那里找到了这个 http://jsfiddle.net/mrajcok/CvKNc/ 示例,但它仍然非常有限..

我还有什么其他选择?编写我自己的 ng-repeat 指令?还是有另一种不写的方法?

【问题讨论】:

  • 让我们换个角度来看。如果你不使用 Angular,你会怎么做?是否可以在不转换数据的情况下以您想要的方式显示它?
  • 如果我不使用 angular,我会这样做 jsfiddle.net/zNW54 或类似的

标签: javascript loops angularjs angularjs-ng-repeat


【解决方案1】:

您可以编写自己的过滤器来过滤掉外部 ng-repeat 的唯一日期,例如:

filter('unique',function(){
  return function(items,field){
    var ret = [], found={};
    for(var i in items){
      var item = items[i][field];
      if(!found[item]){
        found[item]=true;
        ret.push(items[i]);
      }
    }
    return ret;
  }
});

使用以下标记:

<div ng-repeat="dateItem in items | unique:'date' | orderBy:'date'">
<h3>{{dateItem.date}}</h3>
<ul>
  <li ng-repeat="item in items | filter:dateItem.date">
    {{item.name}}
  </li>
</ul>  
</div>

看看this working plnkr example——或者这个updated example with adding items

但是,如果您要拥有很多项目(数百或数千),则此解决方案不是最佳选择。另一种方法是创建更优化的数据结构。您甚至可以通过添加 $watch 来使其与原始数据结构一起使用 - 类似于:

$scope.$watch('items',function(){
  var itemDateMap = {};

  for(var i=0; i<$scope.items.length; i++){
    var item = $scope.items[i], key = item.date;
    if(!itemDateMap[key]){
      itemDateMap[key] = [];
    }
    itemDateMap[key].push(item);
  }

  $scope.itemDateMap=itemDateMap;


},true);

使用此标记:

<div ng-repeat="(date,subItems) in itemDateMap">
<h3>{{date}}</h3>
<ul>
  <li ng-repeat="item in subItems">
    {{item.name}}
  </li>
</ul>  
</div>

Here is an example 您可以在其中添加许多随机项目。

【讨论】:

  • 等等,什么时候可以使用 ng-repeat 作为元素?无论如何,这种表现如何?像 jsfiddle.net/x4sTr 这样在 init 上转换数据结构不是更好吗?还有一件重要的事情是,我将即时编辑和添加新条目..
  • 添加绝对有效plnkr.co/edit/Bkgd4V7y3Eg1qhaeyVAN?p=preview 不过我还是有点担心性能..
  • 对不起,你不能使用 ng-repeat 作为元素。但是你可以将它与任何元素一起使用,所以它可以工作——但这​​是一个不好的例子。我已将其更改为 div。性能方面你应该没问题,除非你有一个非常大的集合。如果您不介意新的数据结构,您可以在 init 函数中进行转换。但是使用我的方法,您不必这样做,您可以轻松地将更多项目添加到原始集合中 - see an updated example
  • 哈 :) 可能会有多达.. 400 个条目.. 每个条目都会有额外的过滤器..
  • 另外那个日期也有时间,所以我不能轻易过滤项目。我只是接受你的回答,这对我没有帮助,但它可能是正确的回答我的问题。
【解决方案2】:

当我有和你一样的需求时,我使用 Object 而不是 Array。

<div ng-repeat="item in data">
  <h1>{{item.date}}</h1>
  <ul ng-repeat="name in item.names">
    <li>{{name}}</li>
  </ul>
</div>

http://jsfiddle.net/shoma/DqDsE/1/

这个问题页面会帮助你。

What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

【讨论】:

  • 问题是你 a) 不能订购对象 b) 不能轻易 push() 进入它们。除此之外,它类似于我在这里描述的转换stackoverflow.com/questions/15943193/…,但不确定它是否会在您编辑或添加新项目时起作用(无需再次重建整个数组/对象)..
猜你喜欢
  • 1970-01-01
  • 2017-07-22
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
相关资源
最近更新 更多