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>
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.
you can do this:
<div ng-repeat="i in [1, 2, 3, 4]">
...
</div>
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);
};
};
_.range
from Underscore or lodash to create the array: $scope.range = _.range(0, n);
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>
$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.
$scope.limit = 2
) and use it like ...|limitTo:limit
-- see updated fiddle
A simpler approach would be (for an example of 5 times):
<div ng-repeat="x in [].constructor(5) track by $index">
...
</div>
Array(5)
(or indeed [...Array(5).keys()]
to get an array [0,1,2,3,4])
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.
$scope._ = _
.
$rootScope
so it can be used everywhere. Put this in your app.run
function just after the app.config
: app.run(function ($rootScope) { $rootScope._ = _; });
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>
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>
_ in (_ = []).length = 33; _ track by $index
slightly smaller
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:
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.
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.
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.
ngRepeat
directive. Using Array.prototype.slice
and idiomatic JS should always be chosen over a library like underscore.js (browser compatibility depending).
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'}];
}
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>
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">
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.
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>
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.
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>
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>
and the 2021 version
*ngFor="let x of [].constructor(number)"
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.
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 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>
I used underscore's times
function as we where already using it on the project, but you can easily replace that with native code.
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)
}
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
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.
track by $index
?
ng-repeat="i in [1,2,3,4]"
$scope.number
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
$scope.number = 5;
<div ng-repeat="n in [] | range:$scope.number">
<span>{{$index}}</span>
</div>
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
Success story sharing
$scope.number
. Angular's digest cycle will automatically recall this function and resize the array any time$scope.number
changes.