15

感谢您花时间阅读本文,我想知道如何使用 ng-repeat 创建一个类似于选项框的网格。我想取一个数组重复第 n 个项目,然后移动到下一行或下一列,直到列出所有项目。例如

假设我有一个数组,[opt1,opt2,opt3,opt4,opt5,opt6,opt7]我想像这样显示它:

opt1 opt2 opt3
opt4 opt5 opt6
opt7
4

5 回答 5

18

这更像是一个样式/标记问题,而不是 AngularJS 问题。如果你真的想,你可以这样做:

<span ng:repeat="(index, value) in array">
    {{value}}<br ng:show="(index+1)%3==0" />
</span>

http://jsfiddle.net/JG3A5/

于 2013-10-24T01:10:34.493 回答
10

对不起我的 HAML 和 Bootstrap3:

.row
  .col-lg-4
    %div{'ng:repeat' => "item in array.slice(0, array.length / 3)"}
      {{item}}
  .col-lg-4
    %div{'ng:repeat' => "item in array.slice(array.length / 3, array.length * 2/3)"}
      {{item}}
  .col-lg-4
    %div{'ng:repeat' => "item in array.slice(array.length * 2/3, array.length)"}
      {{item}}

还有另一个版本,可以使用过滤器:

<div class="row">
  <div class="col-md-4" ng-repeat="remainder in [0,1,2]">
    <span ng-repeat="item in array" ng-if="$index % 3 == remainder">{{item}}</span>
  </div>
</div>
于 2014-02-05T18:44:03.893 回答
6

如果您的所有项目都在一个数组中,那么最好的办法是在 CSS 中创建一个网格。这篇文章应该会有所帮助:http ://css-tricks.com/dont-overthink-it-grids/

您可以使用 ng-repeat 中的 $index 为您的列应用正确的类(在本例中为 4 列网格):

<div class="col-{{ $index % 4 }}"></div>

如果你有一个二维数组(分成行和列),它会打开更多的可能性,比如实际使用 HTML 表。

于 2013-10-23T07:43:17.237 回答
2

I find it easier to simply use ng-repeat combined with ng-if and offsetting any indexes using $index. Mind the jade below:

div(ng-repeat="product in products")
    div.row(ng-if="$index % 2 === 0")
      div.col(ng-init="p1 = products[$index]")
          span p1.Title
      div.col(ng-if="products.length > $index + 1", ng-init="p2 = products[$index + 1]")
          span p2.Title
      div.col(ng-if="products.length <= $index + 1")
于 2015-02-24T14:32:19.657 回答
1

在性能、动态和可读性之间

将逻辑放入 JavaScript 中似乎是最好的方法。我只是硬着头皮研究:

function listToMatrix(list, n) {
    var grid = [], i = 0, x = list.length, col, row = -1;
    for (var i = 0; i < x; i++) {
        col = i % n;
        if (col === 0) {
            grid[++row] = [];
        }
        grid[row][col] = list[i];
    }
    return grid;
}

var matrix = listToMatrix(lists, 3);
console.log('#RedPill', matrix);
  • @参数:(列表,n)
    • 其中 list 是任何数组,n 是每行所需的任意列数
  • @返回:一个拟阵
  • @注意:此函数旨在根据任意数量的列定向拟阵,其行数有差异。换句话说,x = 所需列,y = n。

然后,您可以创建一个角度filter来处理此问题:

筛选:

angular.module('lists', []).filter('matrical', function() {
    return function(list, columns) {
        return listToMatrix(list, columns);
    };
});

控制器:

function listOfListsController($scope) {
    $scope.lists = $http.get('/lists');
}

看法:

<div class="row" ng-repeat="row in (lists | matrical:3)">
    <div class="col col-33" ng-repeat="list in row">{{list.name}}</div>
</div>

有了这个,你可以看到你得到n的行数——每一个都包含“ 3”列。当您更改所需的列数时,您会注意到行数会相应更改(假设列表长度始终相同;))。

这是一个小提琴

请注意,您会得到 ol' Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!。这是因为 Angularmatrical在每次迭代时都会调用该函数。据称,您可以使用as results别名来阻止 Angular 重新评估集合,但我没有运气。为此,最好在控制器内部过滤网格并将该值用于中继器:$filter('matrical')(items)-但如果您在ng-repeat.

我要再次强调,您可能会尝试在您的视图中编写逻辑,从而走上一条黑暗的小巷——但如果您还没有尝试过,我鼓励您在您的视图中尝试它。

编辑

该算法的使用应与矩阵数据结构相结合,以提供pushpopsplice和其他方法 - 如果需要,与适当的逻辑一起补充双向数据绑定。换句话说,数据绑定不会开箱即用(当然),因为当将新项目添加到列表中时,必须重新评估整个列表以保持矩阵的结构完整性。

建议:结合使用$filter('matrical')($scope.list)语法$scope.$watch并重新编译/计算矩阵的项目位置。

干杯!

于 2015-08-28T18:11:50.277 回答