Angular repeat <span> n times

All we need is an easy explanation of the problem, so here it is.

I have a JSON object that contains an int property x, I would like to repeat following code x times

<span class="glyphicon glyphicon-star"/>

ng-repeat does not seem to be indicated as it’s working with collection.
Any suggestion (angular newbie)

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I would use custom filter with ng-repeat:

HTML

<div ng-app='myApp' ng-controller="Main">
    <li ng-repeat="n in [] | range:20">
      <span class="glyphicon glyphicon-star" >{{n}}</span>
    </li>
</div>

filter

app.filter('range', function() {
  return function(val, range) {
    range = parseInt(range);
    for (var i=0; i<range; i++)
      val.push(i);
    return val;
  };
});

Demo Fiddle

Method 2

Shortest answer: 2 lines of code

JS (in your AngularJS controller)

$scope.range = new Array(MAX_STARS); // MAX_STARS should be the most stars you will ever need in a single ng-repeat

HTML

<span class="glyphicon glyphicon-star" ng-repeat="i in range.slice(0,starCount) track by $index"/>

…where starCount is the number of stars that should appear in this location.

Method 3

you can write filter range:

'use strict';

angular.module('app.Filter')
.filter('range', function() {
    return function(input, total) {
        total = parseInt(total);
        for (var i=0; i < total; ++i) {
            input.push(i);
        }
        return input;
    };
});

then use it

<span class="glyphicon glyphicon-star" ng-repeat="i in [] | range:5"/>

5 its your x

Method 4

When I was first starting to play with AngularJS, I found a decent tutorial that walks you through making a custom directive for doing a “Rating” widget in Angularjs.

http://www.befundoo.com/university/tutorials/angularjs-directives-tutorial/

They don’t do anything special other than create a collection of empty objects based on the value of a two-way bound scope variable defined in the directive.

directive('fundooRating', function () {
    return {
        restrict: 'A',
        template: '<ul class="rating">' +
                      '<li ng-repeat="star in stars" class="filled">' +
                          '\u2605' +
                      '</li>' +
                  '</ul>',
        scope: {
            ratingValue: '='
        },
        link: function (scope, elem, attrs) {
            scope.stars = [];
            for (var i = 0; i < scope.ratingValue; i++) {
                scope.stars.push({});
            }
        }
    }
});

The nice thing is that the collection messiness is at least encapsulated inside of the directive, and all the controller has to do is deal with the the numerical rating value. The tutorial also walks you through doing two way linking between the directive and the controller on the rating value scope variable.

IMHO, this is the cleanest solution since AngularJS doesn’t directly support what you want to do. At least here, it is easy to understand what you are trying to do in your controller and view (which is where you want to avoid unnecessary complexity) and you move the hackish-ness into the directive (which you will probably write once and forget).

Method 5

Angular (V1.2.9 and up) includes a filter limitTo:n that will do this out of the box. For example to limit ng-repeat to the first 20 elements use the following syntax:

<div ng-app='myApp' ng-controller="Main">
    <li ng-repeat="n in [] | limitTo:20">
      <span class="glyphicon glyphicon-star" >{{n}}</span>
    </li>
</div>

Documentation for limitTo is here

To be fair the limitTo filter didn’t exist at the time the original question was asked.

Method 6

I answered a similar (duplicate?) question https://stackoverflow.com/a/31864879/1740079. I’ll just repost here as I also ended up here searching for an answer.

(function () {
  angular
    .module('app')
    .directive('repeatTimes', repeatTimes);

  function repeatTimes ($window, $compile) {
    return { link: link };

    function link (scope, element, attrs) {
      var times    = scope.$eval(attrs.repeatTimes),
          template = element.clone().removeAttr('repeat-times');

      $window._(times).times(function (i) {
        var _scope = angular.extend(scope.$new(), { '$index': i });
        var html = $compile(template.clone())(_scope);

        html.insertBefore(element);
      });

      element.remove();
    }
  }
})();

… and the html:

<div repeat-times="4">{{ $index }}</div>

LIVE EXAMPLE

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply