0

I have a simple array of text objects that I want to display in a grid. This is using the Ionic framework.

The grid must be:

  1. Fixed height
  2. Exactly 3 rows
  3. Horizontal scroll (infinite columns)
  4. 2 visible columns with screen width < 768px (phones), 4 visible columns 768px and above (tablets)

I have the media query for the column widths and am using for the horizontal scrolling functionality.

How can I use ng-repeat (maybe with ngif ??) to create the grid, starting in the first column and filling that column with 3 rows before moving to the next column etc etc)

JS

var items = [
{text: "This is item1"},
{text: "This is item2"},
{text: "This is item3"},
.
.
.
]

CSS:

.myGridRow {
  height: 40%;
 }
 .myGridCol {
   width: 50%;
 }
 @media only screen and (min-width : 768px) {
   .myGridCol {
     width: 25%;
   }
 }

HTML

<ion-scroll direction="x">
 <div class="row myGridRow"> <!-- The single container for the whole grid -->

  <div ng-repeat="item in items"> <!-- only do this 3 times before starting a new row -->
   <div class="row"><div class="col myGridCol">{{item.text}}</div></div>
  </div>

</div>
</ion-scroll>

Desired Output

I am stuck here trying to determine how to move to the next column after each 3 rows, or if this is even the right way to do this.

lilbiscuit
  • 2,109
  • 6
  • 32
  • 53
  • Can you share what the desired output should look like? – gnerkus Feb 06 '16 at 20:41
  • @gnerkus I just added desired output to the question. Thanks for looking. – lilbiscuit Feb 06 '16 at 20:50
  • It is a bit hard to read. Could you format it somewhat? You can use hardcoded HTML to show the desired output. – gnerkus Feb 06 '16 at 20:52
  • [plunker](https://plnkr.co/edit/H3rn69xC6QojQoRibCjE?p=info) – lilbiscuit Feb 06 '16 at 21:14
  • I've discussed this issue at length with many people over the years. If you are using a responsive framework to handle your CSS, you shouldn't expect angular to manipulate your data to try to create the screen layout you desire. This is really the job of the CSS; any time you try to "trick" the angular framework into generating new rows instead of letting CSS do that work, you not only add complexity, but you also run the risk of breaking the two way binding with your data. – Claies Feb 07 '16 at 20:33
  • as I have shown in this answer http://stackoverflow.com/a/27215940/2495283 and a few others (this example is using bootstrap, but all responsive frameworks are similar in this regard), you can (and should) simply output the data as presented, and not concern yourself with the row that the data will end up in. With angular in particular, you don't want to have to re-calculate your rows and columns every time you add or remove an item from the middle of an array of elements.... – Claies Feb 07 '16 at 20:37

2 Answers2

1

ng-repeat is constrained to iterate over a collection and will not work with an integer as input. However, you can create a placeholder collection for the number of repetitions required:

$scope.items = [/* The base collection */];
$scope.iterCount = 3; // The number of iterations before a new row is created
$scope.itemCount = Math.floor($scope.items.length / $scope.iterCount);

// Get a collection of items equally spaced from each other. For
// example: getSpacedItems([1, 2, 3, 4], 0, 2) == [1, 3]
$scope.getSpacedItems = function(collection, start, space) {
  var subColl = [];
  for(var i = start; i < collection.length; i += space) {
    result.push(collection[i]);
  }

  return result;
};    

These values can be applied to the view in this manner:

<div>
  <div class="row" ng-repeat="n in [0, 1, 2] track by $index">
    <div class="col myGridCol" ng-repeat="item in getSpacedItems(items, $index, iterCount)">{{item.text}}</div>
  </div>
</div>
gnerkus
  • 11,357
  • 6
  • 47
  • 71
  • This solution fills in the first row first, then second row, etc.... not the first column, second column, etc as required. I need this because this is a horizontal scroll container. – lilbiscuit Feb 07 '16 at 19:51
  • I've made corrections to the solution. I misunderstood the question a little. Thank you for clarifying. – gnerkus Feb 07 '16 at 20:22
0

I suppose the correct solution here - transform array with data on the controller side. So you "rotate" your 2D array and rows become columns, columns become rows. Then you perform just regular output. It is not the task for view side.

sphinks
  • 3,048
  • 8
  • 39
  • 55