ChatGPT解决这个技术问题 Extra ChatGPT

Way to ng-repeat defined number of times instead of repeating over array?

Is there a way to ng-repeat a defined number of times instead of always having to iterate over an array?

For example, below I want the list item to show up 5 times assuming $scope.number equal to 5 in addition incrementing the number so each list item increments like 1, 2, 3, 4, 5

Desired result:

<ul>
   <li><span>1</span></li>
   <li><span>2</span></li>
   <li><span>3</span></li>
   <li><span>4</span></li>
   <li><span>5</span></li>
</ul>

C
Community

Update (9/25/2018)

Newer versions of AngularJS (>= 1.3.0) allow you to do this with only a variable (no function needed):

<li ng-repeat="x in [].constructor(number) track by $index">
    <span>{{ $index+1 }}</span>
</li>
$scope.number = 5;

This was not possible at the time the question was first asked. Credit to @Nikhil Nambiar from his answer below for this update

Original (5/29/2013)

At the moment, ng-repeat only accepts a collection as a parameter, but you could do this:

<li ng-repeat="i in getNumber(number)">
    <span>{{ $index+1 }}</span>
</li>

And somewhere in your controller:

$scope.number = 5;
$scope.getNumber = function(num) {
    return new Array(num);   
}

This would allow you to change $scope.number to any number as you please and still maintain the binding you're looking for.

EDIT (1/6/2014) -- Newer versions of AngularJS (>= 1.1.5) require track by $index:

<li ng-repeat="i in getNumber(number) track by $index">
    <span>{{ $index+1 }}</span>
</li>

Here is a fiddle with a couple of lists using the same getNumber function.


$scope.getNumber = function(num) { var x=new Array(); for(var i=0;i
@Manavendher Incorrect. We do not need to populate the array, we only need it to be the length of $scope.number. Angular's digest cycle will automatically recall this function and resize the array any time $scope.number changes.
@sh0ber. When I need to change the list items based on the value selected in number dropdown. I tried your function first, when it is not working, I changed it to above to update the no. of list items when different number is selected in the dropdown. Can you please check my scenario using your function.
@Manavendher I tried with angular 1.2.x and 1.5.x with same results. Links are 1. stackoverflow.com/questions/40202263/… 2. plnkr.co/edit/zcPr7oUEBBWvCSVkDvml
a
akonsu

you can do this:

<div ng-repeat="i in [1, 2, 3, 4]">
  ...
</div>

worked like a charm, tested on Chrome v. 39.0.2171.95 (64-bit), FF v. 33.1.1 and Safari v. 8.0.2
This works perfectly if you are using it in a pagination control where all you need is
  • {{ i }}
  • @AdityaMP, use this for ranges in javascript stackoverflow.com/a/31989462/3160597
    Consider calling the array constructor for a dynamic-length array, as stated in this answer.
    what if i have to repeat 120 times. Should i go with [1,2,3... 120]?
    P
    Polaris878

    Here is an example of how you could do this. Note that I was inspired by a comment in the ng-repeat docs: http://jsfiddle.net/digitalzebra/wnWY6/

    Note the ng-repeat directive:

    <div ng-app>
        <div ng-controller="TestCtrl">
            <div ng-repeat="a in range(5) track by $index">{{$index + 1}}</div>
        </div>
    </div>
    

    Here is the controller:

    function TestCtrl($scope) {
        $scope.range = function(n) {
            return new Array(n);
        };
    };
    

    You could also use _.range from Underscore or lodash to create the array: $scope.range = _.range(0, n);
    j
    jeffmayeur

    I think this jsFiddle from this thread might be what you're looking for.

    <div ng-app ng-controller="Main">
       <div ng-repeat="item in items | limitTo:2">
           {{item.name}}
       </div>
    </div>
    

    read further down on the google thread link and it describes how you can use 'slice'. e.g. group1: items.slice(0,3), group2: items.slice(3,6), etc.
    This answer will result in the most minimal footprint in your controllers and I believe is the preferred Angular approach as well. IMO accepted answer should be replaced with this.
    This should be the accepted answer (in my opinion) -- Most elegant, most ng-prefered.
    @Cody Unfortunately, no it does not answer the question. OP states "instead of always having to iterate over an array" and "assuming $scope.number equal to 5". The intent was to use an integer variable to define the item count, not hardcode it and not use a predefined array.
    @Cody @sh0ber you can set the limit in your scope ($scope.limit = 2) and use it like ...|limitTo:limit -- see updated fiddle
    n
    nik

    A simpler approach would be (for an example of 5 times):

    <div ng-repeat="x in [].constructor(5) track by $index">
           ...
    </div>
    

    Brilliant. Readable, short, and no silly functions in the controller to return a new array.
    I Love this way.
    I just wish I understood why this syntax works but not Array(5) (or indeed [...Array(5).keys()] to get an array [0,1,2,3,4])
    M
    Mark Roach

    I ran into the same issue. I came across this thread, but didn't like the methods they had here. My solution was using underscore.js, which we had already installed. It's as simple as this:

    <ul>
        <li ng-repeat="n in _.range(1,6)"><span>{{n}}</span></li>
    </ul>
    

    This will do exactly what you're looking for.


    This is good, but note that Underscore isn't in scope by default - you wouldn't be able to use it in your HTML view without doing something like $scope._ = _.
    If you are using lodash or underscore, you should put it in $rootScope so it can be used everywhere. Put this in your app.run function just after the app.config: app.run(function ($rootScope) { $rootScope._ = _; });
    This was a perfect answer for me. It's simple and very straightforward. Since I was repeating using a variable that had a count, I had to do ng-repeat="n in _.range(1, count+1). Thanks for the solution.
    I tried this and while _ shows up in $rootScope, the ng-repeat doesn't render anything.
    F
    Felipe Leão

    I wanted to keep my html very minimal, so defined a small filter that creates the array [0,1,2,...] as others have done:

    angular.module('awesomeApp')
      .filter('range', function(){
        return function(n) {
          var res = [];
          for (var i = 0; i < n; i++) {
            res.push(i);
          }
          return res;
        };
      });
    

    After that, on the view is possible to use like this:

    <ul>
      <li ng-repeat="i in 5 | range">
        {{i+1}} <!-- the array will range from 0 to 4 -->
      </li>
    </ul>
    

    M
    Michael Allan Jackson

    This is really UGLY, but it works without a controller for either an integer or variable:

    integer:

    <span ng-repeat="_ in ((_ = []) && (_.length=33) && _) track by $index">{{$index}}</span>
    

    variable:

    <span ng-repeat="_ in ((_ = []) && (_.length=myVar) && _) track by $index">{{$index}}</span>
    

    Best hack ever! Thanks
    _ in (_ = []).length = 33; _ track by $index slightly smaller
    M
    Mo.

    There are many ways to do this. I was really bothered at having the logic in my controller so I created a simple directive to solve the problem of repeating an element n-times.

    Installation:

    The directive can be installed using bower install angular-repeat-n

    Example:

    <span ng-repeat-n="4">{{$index}}</span
    

    produces: 1234

    It also works using a scope variable:

    <span ng-repeat-n="repeatNum"></span>
    

    Source:

    Github


    This is something they should consider adding to official angular directives
    S
    Sylvain Leroux

    This is only a slight variation on the accepted answer, but you don't really need to create a new function. Only to import 'Array' in the scope:

    <div ng-app="myapp">
        <div ng-controller="ctrlParent">
            <ul>
                <li ng-repeat="i in counter(5) track by $index">
                  <span>{{$index+1}}</span></li>
            </ul>
        </div>
    </div>
    
    var app = angular.module('myapp',[]);
    app.controller('ctrlParent',function($scope){
        $scope.myNumber = 5;
        $scope.counter = Array;
    });
    

    See this fiddle for a live example.


    up to date (2016) and much cleaner !
    J
    JellicleCat

    Easiest answer: 2 lines of code

    JS (in your AngularJS controller)

    $scope.range = new Array(MAX_REPEATS); // set MAX_REPEATS to the most repetitions you will ever need in a single ng-repeat that makes use of this strategy
    

    HTML

    <div ng-repeat="i in range.slice(0,repeatCount) track by $index"></div>
    

    ...where repeatCount is the number of repetitions that should appear in this location.


    I believe this does not let you change the number of repeats in the HTML if it is changed in the controller, unless you wrap it in a function like other answers have done.
    @trysis : I'm not sure if I understand your issue, but you should replace repeatCount with an actual number in the HTML, and as long as that number is less-than-or-equal-to MAX_REPEATS, this will let you set the number of repeats in the HTML.
    In my opinion, this is the most elegant way of limiting the ngRepeat directive. Using Array.prototype.slice and idiomatic JS should always be chosen over a library like underscore.js (browser compatibility depending).
    Not a bad solution, +1, but I think this answer is easier, and avoids cluttering the controller.
    S
    Sheelpriy

    angular gives a very sweet function called slice.. using this you can achieve what you are looking for. e.g. ng-repeat="ab in abc.slice(startIndex,endIndex)"

    this demo :http://jsfiddle.net/sahilosheal/LurcV/39/ will help you out and tell you how to use this "making life easy" function. :)

    html:

    <div class="div" ng-app >
        <div ng-controller="Main">
            <h2>sliced list(conditional NG-repeat)</h2>
            <ul ng-controller="ctrlParent">
                <li ng-repeat="ab in abc.slice(2,5)"><span>{{$index+1}} :: {{ab.name}} </span></li>
            </ul>
            <h2>unsliced list( no conditional NG-repeat)</h2>
             <ul ng-controller="ctrlParent">
                <li ng-repeat="ab in abc"><span>{{$index+1}} :: {{ab.name}} </span></li>
            </ul>
    
        </div>
    

    CSS:

    ul
    {
    list-style: none;
    }
    .div{
        padding:25px;
    }
    li{
        background:#d4d4d4;
        color:#052349;
    }
    

    ng-JS:

     function ctrlParent ($scope) {
        $scope.abc = [
         { "name": "What we do", url: "/Home/AboutUs" },
         { "name": "Photo Gallery", url: "/home/gallery" },
         { "name": "What we work", url: "/Home/AboutUs" },
         { "name": "Photo play", url: "/home/gallery" },
         { "name": "Where", url: "/Home/AboutUs" },
         { "name": "playground", url: "/home/gallery" },
         { "name": "What we score", url: "/Home/AboutUs" },
         { "name": "awesome", url: "/home/gallery" },
         { "name": "oscar", url: "/Home/AboutUs" },
         { "name": "american hustle", url: "/home/gallery" }
        ];
    }
    function Main($scope){
        $scope.items = [{sort: 1, name: 'First'}, 
                        {sort: 2, name: 'Second'}, 
                        {sort: 3, name: 'Third'}, 
                        {sort: 4, name:'Last'}];
        }
    

    D
    DrogoNevets

    Heres an answer for angular 1.2.x

    Basically it is the same, with the slight modification of of the ng-repeat

    <li ng-repeat="i in getNumber(myNumber) track by $index">
    

    here is the fiddle: http://jsfiddle.net/cHQLH/153/

    this is because angular 1.2 doesn't allow duplicate values in the directive. This means if you are trying to do the following, you will get an error.

    <li ng-repeat="x in [1,1,1]"></li>
    

    a
    akaashanky

    You can use the ng-if directive with ng-repeat

    So, if num is the number of times you need the element repeated:

    <li ng-repeat="item in list" ng-if="$index < num">
    

    For those of you who like clean markup... Keep in mind using ng-repeat in this way will still output it's commented tags (<!-- ngIf: $index < num --> etc..). There simply won't be any li elements for the DOM to render. Check a "view source" on the results pane here to see what I mean.
    M
    Mo.

    For users using CoffeeScript, you can use a range comprehension:

    Directive

    link: (scope, element, attrs) ->
      scope.range = [1..+attrs.range]
    

    or Controller

    $scope.range = [1..+$someVariable]
    $scope.range = [1..5] # Or just an integer
    

    Template

    <div ng-repeat="i in range">[ the rest of your code ]</div>
    

    o
    omikes

    Expanding a bit on Ivan's first answer, you can use a string as the collection without a track by statement so long as the characters are unique, so if the use-case is less than 10 numbers (as it is in the question) I would simply do:

    <ul>
       <li ng-repeat="n in '12345'"><span>{{n}}</span></li>
    </ul>
    

    Which is a bit jenky, sure, but simple enough to look at and not particularly confusing.


    e
    elceka

    You can use this example.

    Inside controller:

    $scope.data = {
        'myVal': 33,
        'maxVal': 55,
        'indexCount': function(count) {
            var cnt = 10;
            if (typeof count === 'number') {
                cnt = count;
            }
            return new Array(cnt);
        }
    };
    

    Example for select element at the HTML code side:

    <select ng-model="data.myVal" value="{{ data.myVal }}">
        <option ng-repeat="i in data.indexCount(data.maxVal) track by $index" value="{{ $index + 1 }}">{{ $index + 1 }}</option>
    </select>
    

    K
    Karanvir Kang

    First, create an angular filter using LoDash:

    angular.module('myApp').filter('times', function(){
       return function(value){
          return _.times(value || 0);
       }
    });
    

    The LoDash times function is capable of handling null, undefined, 0, numbers, and string representation of numbers.

    Then, use it in your HTML as this:

    <span ng-repeat="i in 5 | times">
     <!--DO STUFF-->
    </span>
    

    or

    <span ng-repeat="i in myVar | times">
     <!--DO STUFF-->
    </span>
    

    J
    Johansrk

    and the 2021 version

    *ngFor="let x of [].constructor(number)"
    

    N
    Nik Dow

    Angular provides filters to modify a collection. In this case the collection would be null, i.e. [], and the filter also takes arguments, as follows:

    <div id="demo">
        <ul>
            <li ng-repeat="not in []|fixedNumber:number track by $index">{{$index}}</li>
        </ul>
    </div>
    

    JS:

    module.filter('fixedNumber', function() {
        return function(emptyarray, number) {
            return Array(number);
        }
    });
    
    module.controller('myCtrl', ['$scope', function($scope) {
        $scope.number = 5;
    }]);
    

    This method is very similar to those proposed above and isn't necessarily superior but shows the power of filters in AngularJS.


    v
    vonwolf

    If n is not too high, another option could be to use split('') with a string of n characters :

    <div ng-controller="MainCtrl">
    <div ng-repeat="a in 'abcdefgh'.split('')">{{$index}}</div>
    </div>
    

    i believe the split is unnecessary here. a string is already an array of characters.
    i
    ichigolas

    I encountered the same problem and this is what I came out with:

    (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

    I used underscore's times function as we where already using it on the project, but you can easily replace that with native code.


    a
    adswebwork

    I needed a more dynamic solution to this - where I could increment the repeat.

    HTML

    <div ng-repeat="n in newUserCount">
    <input type="text" value="" name="newuser{{n}}"/>
    </div>
    

    Duplicator Control

    <span class="helper" ng-click="duplicateUser()">
    Create another user with the same permissions
    </span>
    

    JS

     $scope.newUserCount = Array('1');
    var primaryValue = 1;
    $scope.duplicateUser = function()
    {
        primaryValue++;
        $scope.newUserCount.push(primaryValue)
    }
    

    m
    msanford

    I am creating a reusable directive where the max number will come from another ng-repeat. So, this is an edit over the best voted answer.

    Just change the code at controller to this -

    $scope.getNumber = function(num) {
        var temp = [];
        for(var j = 0; j < num; j++){
            temp.push(j)
        }
        return temp; 
    }
    

    This will return a new array with specified number of iterations


    I
    Ivan Ferrer Villa

    since iterating over a string it will render an item for each char:

    <li ng-repeat = "k in 'aaaa' track by $index">
       {{$index}} //THIS DOESN'T ANSWER OP'S QUESTION. Read below.
    </li>
    

    we can use this ugly but no-code workaround using the number|n decimal places native filter.

     <li ng-repeat="k in (0|number:mynumber -2 ) track by $index">
        {{$index}}
     </li>
    

    this way we'll have mynumber elements with no extra code. Say '0.000'.
    We use mynumber - 2 to compensate 0.
    It won't work for numbers below 3, but might be useful in some cases.


    did you use track by $index?
    this is ghetto af. if you're going to be forced to have a char for each iteration you might as well do ng-repeat="i in [1,2,3,4]"
    of course, but OP wants the iteration to be n times based on a variable $scope.number
    why not 'abcd' instead of 'aaaa' and then scrap the track by?
    aaaa was an example to explain my -not very elegant- workaround. Using hardcoded 'aaaa' or 'abcd' you get a fixed length list, but adding mynumber-2 decimals to 0, you get a 'string' with mynumber chars. Say mynumber=5, you get '0.000', then we iterate that using $index
    D
    DuFuS
    $scope.number = 5;
    
    <div ng-repeat="n in [] | range:$scope.number">
          <span>{{$index}}</span>
    </div>
    

    P
    Pallepassion

    simple way:

        public defaultCompetences: Array<number> = [1, 2, 3];
    

    in the component/controller and then:

        <div ng-repeat="i in $ctrl.defaultCompetences track by $index">
    

    This code is from my typescript project but could be rearranged to pure javascript