Angular does provide some support for a for loop using numbers within its HTML directives:
<div data-ng-repeat="i in [1,2,3,4,5]">
do something
</div>
But if your scope variable includes a range that has a dynamic number then you will need to create an empty array each time.
In the controller
var range = [];
for(var i=0;i<total;i++) {
range.push(i);
}
$scope.range = range;
In the HTML
<div data-ng-repeat="i in range">
do something
</div>
This works, but it is unnecessary since we won't be using the range array at all within the loop. Does anyone know of setting a range or a regular for min/max value?
Something like:
<div data-ng-repeat="i in 1 .. 100">
do something
</div>
I tweaked this answer a bit and came up with this fiddle.
Filter defined as:
var myApp = angular.module('myApp', []);
myApp.filter('range', function() {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++)
input.push(i);
return input;
};
});
With the repeat used like this:
<div ng-repeat="n in [] | range:100">
do something
</div>
I came up with a slightly different syntax which suits me a little bit more and adds an optional lower bound as well:
myApp.filter('makeRange', function() {
return function(input) {
var lowBound, highBound;
switch (input.length) {
case 1:
lowBound = 0;
highBound = parseInt(input[0]) - 1;
break;
case 2:
lowBound = parseInt(input[0]);
highBound = parseInt(input[1]);
break;
default:
return input;
}
var result = [];
for (var i = lowBound; i <= highBound; i++)
result.push(i);
return result;
};
});
which you can use as
<div ng-repeat="n in [10] | makeRange">Do something 0..9: {{n}}</div>
or
<div ng-repeat="n in [20, 29] | makeRange">Do something 20..29: {{n}}</div>
I came up with an even simpler version, for creating a range between two defined numbers, eg. 5 to 15
HTML:
<div ng-app='myApp' ng-controller="Main">
<li ng-repeat="n in range(5,15)">test {{n}}</li>
</div>
Controller:
myApp.controller('Main', ['$scope', function ($scope) {
$scope.range = function(min, max, step){
step = step || 1;
var input = [];
for (var i = min; i <= max; i += step) input.push(i);
return input;
};
});
A short way of doing this would be to use Underscore.js's _.range() method. :)
http://underscorejs.org/#range
// declare in your controller or wrap _.range in a function that returns a dynamic range.
var range = _.range(1, 11);
// val will be each number in the array not the index.
<div ng-repeat='val in range'>
{{ $index }}: {{ val }}
</div>
For those new to angularjs. The index can be gotten by using $index.
For example:
<div ng-repeat="n in [] | range:10">
do something number {{$index}}
</div>
Which will, when you're using Gloopy's handy filter, print:
do something number 0
do something number 1
do something number 2
do something number 3
do something number 4
do something number 5
do something number 6
do something number 7
do something number 8
do something number 9
I use my custom ng-repeat-range
directive:
/**
* Ng-Repeat implementation working with number ranges.
*
* @author Umed Khudoiberdiev
*/
angular.module('commonsMain').directive('ngRepeatRange', ['$compile', function ($compile) {
return {
replace: true,
scope: { from: '=', to: '=', step: '=' },
link: function (scope, element, attrs) {
// returns an array with the range of numbers
// you can use _.range instead if you use underscore
function range(from, to, step) {
var array = [];
while (from + step <= to)
array[array.length] = from += step;
return array;
}
// prepare range options
var from = scope.from || 0;
var step = scope.step || 1;
var to = scope.to || attrs.ngRepeatRange;
// get range of numbers, convert to the string and add ng-repeat
var rangeString = range(from, to + 1, step).join(',');
angular.element(element).attr('ng-repeat', 'n in [' + rangeString + ']');
angular.element(element).removeAttr('ng-repeat-range');
$compile(element)(scope);
}
};
}]);
and html code is
<div ng-repeat-range from="0" to="20" step="5">
Hello 4 times!
</div>
or simply
<div ng-repeat-range from="5" to="10">
Hello 5 times!
</div>
or even simply
<div ng-repeat-range to="3">
Hello 3 times!
</div>
or just
<div ng-repeat-range="7">
Hello 7 times!
</div>
Nothing but plain Javascript (you don't even need a controller):
<div ng-repeat="n in [].constructor(10) track by $index">
{{ $index }}
</div>
Very useful when mockuping
You can use 'after' or 'before' filters in angular.filter module (https://github.com/a8m/angular-filter)
$scope.list = [1,2,3,4,5,6,7,8,9,10]
HTML:
<li ng-repeat="i in list | after:4">
{{ i }}
</li>
result: 5, 6, 7, 8, 9, 10
Simplest no code solution was to init an array with the range, and use the $index + however much I want to offset by:
<select ng-init="(_Array = []).length = 5;">
<option ng-repeat="i in _Array track by $index">{{$index+5}}</option>
</select>
JS (in your AngularJS controller)
$scope.range = new Array(MAX_REPEATS); // MAX_REPEATS should be the most repetitions you will ever need in a single ng-repeat
HTML
<div data-ng-repeat="i in range.slice(0,myCount) track by $index"></div>
...where myCount
is the number of stars that should appear in this location.
You can use $index
for any tracking operations. E.g. if you want to print some mutation on the index, you might put the following in the div
:
{{ ($index + 1) * 0.5 }}
An improvement to @Mormegil's solution
app.filter('makeRange', function() {
return function(inp) {
var range = [+inp[1] && +inp[0] || 0, +inp[1] || +inp[0]];
var min = Math.min(range[0], range[1]);
var max = Math.max(range[0], range[1]);
var result = [];
for (var i = min; i <= max; i++) result.push(i);
if (range[0] > range[1]) result.reverse();
return result;
};
});
usage
<span ng-repeat="n in [3, -3] | makeRange" ng-bind="n"></span>
3 2 1 0 -1 -2 -3
<span ng-repeat="n in [-3, 3] | makeRange" ng-bind="n"></span>
-3 -2 -1 0 1 2 3
<span ng-repeat="n in [3] | makeRange" ng-bind="n"></span>
0 1 2 3
<span ng-repeat="n in [-3] | makeRange" ng-bind="n"></span>
0 -1 -2 -3
Very simple one:
$scope.totalPages = new Array(10);
<div id="pagination">
<a ng-repeat="i in totalPages track by $index">
{{$index+1}}
</a>
</div>
I tried the following and it worked just fine for me:
<md-radio-button ng-repeat="position in formInput.arrayOfChoices.slice(0,6)" value="{{position}}">{{position}}</md-radio-button>
Angular 1.3.6
Using UnderscoreJS:
angular.module('myModule')
.run(['$rootScope', function($rootScope) { $rootScope.range = _.range; }]);
Applying this to $rootScope
makes it available everywhere:
<div ng-repeat="x in range(1,10)">
{{x}}
</div>
I whipped this up and saw it might be useful for some. (Yes, CoffeeScript. Sue me.)
app.directive 'times', ->
link: (scope, element, attrs) ->
repeater = element.html()
scope.$watch attrs.times, (value) ->
element.html ''
return unless value?
element.html Array(value + 1).join(repeater)
To use:
<div times="customer.conversations_count">
<i class="icon-picture></i>
</div>
Can this get any simpler?
I'm wary about filters because Angular likes to re-evaluate them for no good reason all the time, and it's a huge bottleneck if you have thousands of them like I do.
This directive will even watch for changes in your model, and update the element accordingly.
The code below defines a method range()
available to the entire scope of your application MyApp
. Its behaviour is very similar to the Python range()
method.
angular.module('MyApp').run(['$rootScope', function($rootScope) {
$rootScope.range = function(min, max, step) {
// parameters validation for method overloading
if (max == undefined) {
max = min;
min = 0;
}
step = Math.abs(step) || 1;
if (min > max) {
step = -step;
}
// building the array
var output = [];
for (var value=min; value<max; value+=step) {
output.push(value);
}
// returning the generated array
return output;
};
}]);
With one parameter:
<span ng-repeat="for i in range(3)">{{ i }}, </span>
0, 1, 2,
With two parameters:
<span ng-repeat="for i in range(1, 5)">{{ i }}, </span>
1, 2, 3, 4,
With three parameters:
<span ng-repeat="for i in range(-2, .7, .5)">{{ i }}, </span>
-2, -1.5, -1, -0.5, 0, 0.5,
Set Scope in controller
var range = [];
for(var i=20;i<=70;i++) {
range.push(i);
}
$scope.driverAges = range;
Set Repeat in Html Template File
<select type="text" class="form-control" name="driver_age" id="driver_age">
<option ng-repeat="age in driverAges" value="{{age}}">{{age}}</option>
</select>
This is the simplest variant: just use array of integers....
<li ng-repeat="n in [1,2,3,4,5]">test {{n}}</li>