AngularJS ng-repeat to populate grid from array

徘徊边缘 提交于 2019-12-10 18:30:45

问题


Thanks in advance for reading. I am trying to utilize angular's ng-repeat to render objects from an array into an Nx3 Table. For the sake of example let's consider a 3x3 table.

Here is a simplified example of the array:

objects = [{"text": "One, One"},{"text": "One, Two"},{"text": "One, Three"},
           {"text": "Two, One"},{"text": "Two, Two"},{"text": "Two, Three"},
           {"text": "Three, One"},{"text": "Three, Two"},{"text": "Three, Three"}];

The "text" field describes where in the 3x3 grid matrix each element should appear. I would like to use ng-repeat on objects to generate html that looks like this:

<table>
  <tr>
    <td>One, One</td>
    <td>One, Two</td>
    <td>One, Three</td>
  </tr>
  <tr>
    <td>Two, One</td>
    <td>Two, Two</td>
    <td>Two, Three</td>
  </tr>
  <tr>
    <td>Three, One</td>
    <td>Three, Two</td>
    <td>Three, Three</td>
  </tr>
</table>

Is there any way to achieve this without needing to break up the array into separate arrays for each row?


回答1:


Best possibly way would be to alter your view model in the controller and bind that to ng-repeat (But you already said you do not want to do that). If you ever plan to take that route you can also take a look at user @m59 answer where he creates a reusable filter to do it. However this is just a simple answer making use of built in filter's configurable evaluation expression where we can return truthy/falsy value to determine if they need to be repeated or not. This eventually has the only advantage of no need to create 2 ng-repeat blocks (But that is not so bad though). So in your controller add a function on the scope,

$scope.getFiltered= function(obj, idx){
   //Set a property on the item being repeated with its actual index
   //return true only for every 1st item in 3 items
    return !((obj._index = idx) % 3); 
}

and in your view apply the filter:

  <tr ng-repeat="obj in objects | filter:getFiltered">
    <!-- Current item, i.e first of every third item -->
    <td>{{obj.text}}</td> 
    <!-- based on the _index property display the next 2 items (which have been already filtered out) -->
    <td>{{objects[obj._index+1].text}}</td>
    <td>{{objects[obj._index+2].text}}</td>
  </tr>

Plnkr




回答2:


I wanted to do the exact same thing.

Convert an array into a matrix/ grid

I have an array which i wanted to convert into a grid/matrix of column size 4. the following implementation worked for me. You can use the two counters : row and col as you like in side the nested ng-repeat

In my case number of columns is 3. But you can replace that 3 with a variable everywhere. h.seats is my array of the objects and i want to print either X or - based on value of element in that array

<div class="table-responsive">
    <table class="table table-bordered">
        <thead>
            <tr>
                <th ng-repeat="n in [].constructor(3 + 1) track by $index">{{$index}}</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="(row, y) in getNumber(h.seats.length, 3) track by $index">
                <td>{{row+1}}</td>
                <td class="text-primary"
                    ng-repeat="(col, t) in h.seats track by $index"
                    ng-if="col >= (row)*3 && col < (row+1)*3">
                        <span ng-show="t.status"> X </span> 
                        <span ng-show="!t.status"> - </span>
                </td>
            </tr>
        </tbody>
    </table>
</div>

<th ng-repeat="n in [].constructor(3 + 1) track by $index">{{$index}}</th> prints the header row with column number at the top. getNumber(h.seats.length, 3) returns me the number of rows of that table as follows

.controller('CustomViewController', function ($scope, Principal, $state) {

    $scope.getNumber = function(length, columns) {
        return new Array(parseInt(length / columns + 1, 10));   
    }

The line ng-if="col >= (row)*3 && col < (row+1)*3" is important logic to calculate which elements should be put in that row. The output looks like below

0  1  2  3 
1  e1 e2 e3 
2  e4 e5 e6 
3  e7 e8 

Refer to following link for details of how row and col counters are used: https://stackoverflow.com/a/35566132/5076414



来源:https://stackoverflow.com/questions/28057513/angularjs-ng-repeat-to-populate-grid-from-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!