Ng-Repeat array to rows and columns

前端 未结 5 1824
梦谈多话
梦谈多话 2021-02-04 06:45

Thanks for taking the time to read this, I was wondering how I might be able to use ng-repeat to create a grid like box of options. I would like to take an array repeat nth num

相关标签:
5条回答
  • 2021-02-04 07:26

    If all of your items are in one single array, your best bet is to make a grid in CSS. This article should be helpful: http://css-tricks.com/dont-overthink-it-grids/

    You can use $index from ng-repeat to apply the correct class for your column (in this case a 4 column grid):

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

    If you have a 2 dimensional array (split into rows and columns) that opens up more possibilities like actually using an HTML table.

    0 讨论(0)
  • 2021-02-04 07:29

    Between Performance, Dynamics and Readability

    It seems putting the logic in your JavaScript is the best method. I would just bite-the-bullet and look into:

    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);
    
    • @ Params: (list, n)
      • Where list is any array and n is an arbitrary number of columns desired per row
    • @ Return: A matroid
    • @ Note: This function is designed to orient a matroid based upon an arbitrary number of columns with variance in its number of rows. In other words, x = desired-columns, y = n.

    You can then create an angular filter to handle this:

    Filter:

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

    Controller:

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

    View:

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

    With this, you can see you get n number of rows -- each containing "3" columns. When you change the number of desired columns, you'll notice the number of rows changes accordingly (assuming the list-length is always the same ;)).

    Here's a fiddle.

    Note, that you get the ol' Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!. This is because Angular is recalling the matrical function upon every iteration. Allegedly, you can use the as results alias to prevent Angular from reevaluating the collection, but I had no luck. For this, it may be better to filter the grid inside of your controller and use that value for your repeater: $filter('matrical')(items) -- but please post back if you come across an elegant way of filtering it in the ng-repeat.

    I would stress, again, you're probably heading down a dark alley by trying to write the logic in your view -- but I encourage you to try it in your view if you haven't already.

    Edit

    The use of this algorithm should be combined with a Matrical Data-Structure to provide methods of push, pop, splice, and additional methods -- in tandem with appropriate logic to complement Bi-Directional Data-Binding if desired. In other words, data-binding will not work out of the box (of course) as when a new item is added to your list, a reevaluation of the entire list must take place to keep the matrix's structural integrity.

    Suggestion: Use the $filter('matrical')($scope.list) syntax in combination with $scope.$watch and recompile/calculate item-positions for the matrix.

    Cheers!

    0 讨论(0)
  • 2021-02-04 07:30

    This is more a styling/markup problem than an AngularJS one. If you really want to, you can do:

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

    http://jsfiddle.net/JG3A5/

    0 讨论(0)
  • 2021-02-04 07:32

    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")
    
    0 讨论(0)
  • 2021-02-04 07:38

    Sorry for my HAML and 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}}
    

    There is another version, with possibility to use filters:

    <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>
    
    0 讨论(0)
提交回复
热议问题