Best way to list 2 elements per line with ng-repeat in angular?

I have an array of objects and I want to display 2 for each row using ng-repeat.

The solution I came up with is the following:

<div ng-repeat="element in elements"> <div layout="row" ng-if="$even"> <div flex> <span>{{ elements[$index].name }}</span> </div> <div flex> <span>{{ elements[$index+1].name }}</span> </div> </div> </div> 

The problem is that with this, I cannot properly filter the content using | filter | filter , since it displays the filtered elements and the following.

What is the best way to solve the problem?

Sorry for my bad english, this is not my first language. Thank you in advance.

+7
javascript angularjs angularjs-ng-repeat ng-repeat
source share
4 answers

A good solution would be, as @Joshua Ohana said in the comments, pre-process your array and then use your solution.

The quick and dirty option (without pre-processing) based on your decision will consist in filtering the array inside the span element:

 <div ng-repeat="element in elements"> <div layout="row" ng-if="$even"> <div flex> <span>{{ (elements | filter:<yourFilterHere>)[$index].name }}</span> </div> <div flex> <span>{{ (elements | filter:<yourFilterHere>)[$index+1].name }}</span> </div> </div> </div> 

but I like the preprocessing option.

+2
source share

I think that instead of showing two elements on ng-repeat, you should try to find a way to achieve the same result without additional complexity. You can do something like this:

 <div ng-repeat="element in elements | filter"> <div layout="row" ng-if="$even"> <div flex> <span>{{ element.name }}</span> </div> </div> <div flex ng-if="$odd"> <span>{{ element.name }}</span> </div> </div> 
0
source share

I just started with AngularJS for about 2 weeks and I was not able to get a solid answer to this question. So I decided to take care of myself, that's what I came up with.

Two filters are listed below: nRange returns an array containing the sequence increased by n, which is limited by numItems - numItems% n. Where the range returns an array of a linear sequence starting at 0. Filters can be thought of as helper functions for the following AngularJS code.

 /* Pre: [] | nRange:numItems:n Post: Ex.1: [] | nRange:5:2 --> [0,2,4] Ex.1: [] | nRange:5:3 --> [0,3] */ website.filter('nRange', function() { return function(input, numItems, n) { if(numItems == 0) { return null; } range = numItems - numItems%n; for(i = 0; i <= range-n; i += n) { input.push(i); } if(numItems%n != 0) { input.push(range); } return input; }; }); /* Pre: [] | range:numItems Post: Ex.1: [] | range:5 --> [0,1,2,3,4] Ex.1: [] | range:2 --> [0,1] */ website.filter('range', function() { return function(input, numItems) { for (var i=0; i<=numItems; i++) { input.push(i); } return input; }; }); 

$ Scope includes projects and the number of projects in the projectCols line. By defining projectCols, we can quickly and easily change the layout.

 <div class="container"> <div class="row" ng-repeat="i in [] | nRange:projects.length:projectCols"> <div class="col-md-{{12/projectCols}} col-sm-12 col-xs-12" ng-repeat="j in [] | range:projectCols-1"> <project-item ng-if="projects[i+j]" info="projects[i+j]"></project-item> </div> </div> </div> 

The following HTML uses filters to populate project elements. What the code does, it uses nRange to count for a certain amount, in other words, it's like a for loop with i + = n for incrementing. Then the range provides a subrange, in total it can be considered as the following:

 for(i = 0; i < nRange; i+=n) { for(j = 0; i < range; i++) { if($scope.projects[i+j]) { // If the project exist // Display it in the view } } } 

Together, this allows you to have 2, 3, 4, or 6 projects per line.

I also created some css classes to display the project correctly.

 .project { border: 1px solid gray; border-radius: 5px; background: whitesmoke; } .col-md-6 .project { margin: 30px; padding: 30px; height: 450px; } .col-md-4 .project { margin: 20px; padding: 20px; height: 400px; } .col-md-3 .project { margin: 10px; padding: 10px; height: 400px; } .col-md-2 .project { margin: 5px; padding: 5px; height: 400px; } 

Here is my repository for my site that contains my full implementation.

 https://github.com/arjo1203/website 

Here is a live demo! http://www.jraraujo.com/

0
source share

I would use ng-repeat to display individual list items in an unordered list, and then use CSS to style each li so that it is 50% of the width of the container (or 49% usually works more consistently) and make each li a inline-block style so that they swim two on the line.

I am working in Angular4 at the moment, so I canโ€™t switch gears to Angular1.x code, but here is the layout in pure HTML that you can check, and then, if this seems to solve our problem, change your code.

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"> <html> <head> <link rel="stylesheet" href="./arraylist.css"> </head> <body> <ul class="array-list"> <li>One Item</li> <li>Two Item</li> <li>Three Item</li> <li>Four Item</li> <li>Five Item</li> <li>Six Item</li> <li>Seven Item</li> <li>Eight Item</li> </ul> </body> </html> 

And an array of list.css file:

 ul.array-list { display: block; margin: 0; padding: 0; } li { display: inline-block; width: 49%; } 

Your Angular code will look something like this:

 <div ng-repeat="element in elements"> <ul class="array-list"> <li> {{ elements[$index].name }} </li> </ul> </div> 

This does not realize what I am assuming is the alternation of dark / light gray lines, but you can probably develop a way to stylize this or not stylize it if this is not particularly important.

The important thing is that since you are repeating individual elements when you filter out some of them, the elements below are automatically overflowed to fill in the blanks, and you will not get a conflicting interface as a result of displaying some values โ€‹โ€‹because the element in which they are connected matches the filter .

0
source share

All Articles