3

I have a table row which I want to repeat and every row have only 4 td

<table>
 <tr>
 <td ng-repeat="team in Teams">{{team}}</td>
 </tr>
</table>

How I can repeat Td, but on every 4 td create another tr and close previous one

naCheex
  • 1,131
  • 3
  • 14
  • 34
  • post the structure of your `Teams` model – AdityaParab Oct 09 '15 at 10:25
  • 1
    lets suppose its an array [1,2,3,4,5,6,7,8], I dnt think it matters – naCheex Oct 09 '15 at 10:26
  • a better way would be to modify the `Teams` variable to be something like `[[1,2,3,4],[5,6,7,8]]` – AdityaParab Oct 09 '15 at 10:27
  • 1
    and then use `{{t}}` – AdityaParab Oct 09 '15 at 10:30
  • you can use `lodash` (a js library) to do this – AdityaParab Oct 09 '15 at 10:31
  • there is a method `chunk()` that can get this done. `$scope.Teams = _.chunk($scope.Teams,4);` – AdityaParab Oct 09 '15 at 10:32
  • There's no need to modify the Teams variable.. changing "backend" code to achieve UI presentation seems like a bad idea, especially when you can achieve this natively with angular - see my answer :) – Sk93 Oct 09 '15 at 10:41
  • http://jsfiddle.net/kishoresahas/ak20wgys/ is this what ur expecting? – Kishore Sahasranaman Oct 09 '15 at 10:43
  • @Sk93 : No need to change backend implementation. It can be done on the UI itself before passing it to the template. :) – AdityaParab Oct 09 '15 at 12:16
  • @AdityaParab not if it's coming from an ajax call. Then you'll need to rebuild it in JavaScript, on the client. We don't know where this data comes from, so can't make any assumptions. I referred to it as "backend", in quotations, to signify the different between some unknown data source, and actual backend, as I don't know either :) – Sk93 Oct 12 '15 at 06:29
  • You need not know where the data is coming from. If you (the general you, not YOU you :D ) are building the application, you know where the data is `received`. So you can just add a small piece of code to make it work on your end. I agree on your definition of "backend" but as long as you have good design (by that I mean concerns are separated well) then you need not worry about where the data is coming from. :) – AdityaParab Oct 12 '15 at 09:52
  • @Sk93 : Please take a look at the answer I posted on this question to understand more about how you can modify the data (post reception) inline. :D – AdityaParab Oct 12 '15 at 09:53
  • @AdityaParab whilst I know we CAN change it in the UI, it still doesn't strike me as the right approach. If you can use the data as provided, then you aren't introducing any additional processing time at the client. Wheras, if we take your example, you've introduced an additional loop of the entire array that must take place, before rendering can complete. Granted, if we assume this is a small array, it's not likely to be noticeable, but on larger or more complex arrays, this could turn into a noticeable slight delay, or even worse. :) – Sk93 Oct 12 '15 at 10:42
  • @AdityaParab to demonstrate, I created a simple test that loaded 500 entries into the Teams array and built the table via my method. the DOMContentLoaded time was 107ms (https://jsfiddle.net/4x0nhxbL/). I then used the same array and built the table via your method. This time the DOMContentLoaded time was 513ms (http://jsfiddle.net/04jLg5zf/). (timings taken when pages run locally, not on jsfiddle, and with a local copy of angular rather than using CDN) – Sk93 Oct 12 '15 at 11:30

3 Answers3

4

This can be achieved by utilising the $index special property.

If we move the ng-repeat to the TR element, it will produce a TR every time. We can then combat that behaviour by adding an ng-if attribute that compares the current $index against modulus 4, meaning the TR will only be added every four iterations of the ng-repeat.

With this done, we then can again use $index within the four child TD elements.

For the second and third elements, we need to increase the index by one, two and three respectively to get to the relevant positions inside the "Team" array. However, that poses a problem if that array isn't divisible by 4 perfectly. So, finally, to counter that problem, we add a final set of ng-if attributes to the secondm third and fourth TD elements to ensure that they don't get added if there isn't infact any objects at the desired position in the array.

Resulting in the following HTML:

<table>
 <tr ng-repeat="team in Teams" ng-if="$index % 4 == 0">
    <td>{{Teams[$index]}}</td>
    <td ng-if="$index+1 < Teams.length">{{Teams[$index + 1]}}</td>
    <td ng-if="$index+2 < Teams.length">{{Teams[$index + 2]}}</td>
    <td ng-if="$index+3 < Teams.length">{{Teams[$index + 3]}}</td>
 </tr>
</table>

You can find more info on the special properties of ng-repeat here: Documentation: https://docs.angularjs.org/api/ng/directive/ngRepeat

Sk93
  • 3,676
  • 3
  • 37
  • 67
1

https://docs.angularjs.org/api/ng/directive/ngRepeat

You could get the value from $index and put a condition on $index % 4 which would had a

</tr><tr> 

!

Roughly would be like that :

repeat with team in Teams
IF $index%4 == 0
   </tr><tr>
{{team}}
end-repeat

Not totally familiar with the syntax used by Angular but I guess you'll get the idea :)

Alexandre Beaudet
  • 2,774
  • 2
  • 20
  • 29
  • I tried like this : `{{($index%4==0)?'':''}}` It doesn't parse html ... – naCheex Oct 09 '15 at 10:30
  • http://stackoverflow.com/questions/27211799/angular-ng-repeat-add-bootstrap-row-every-3-or-4-cols Isn't this link helping ? Think the guy want the same result as you do – Alexandre Beaudet Oct 09 '15 at 10:31
1

Although this is an answered question, here is another alternative that makes use of filters

Just add a new filter in your app like

    app.filter('GroupBy', function(){
        return function(data,array, step) {
            var result = [];
            for(var i = 0; i<array.length;i+=step){
                var _step = i+step;
                result.push(array.slice(i,_step));
            }
            return result;
        };
    });

And in your template, use

<tr ng-repeat="team in Teams | GroupBy:Teams :4">
    <td ng-repeat="t in team">{{t}}</td>
</tr>
AdityaParab
  • 7,024
  • 3
  • 27
  • 40