¿Manera de repetir ng el número definido de veces en lugar de repetir sobre una matriz?

417

¿Hay alguna forma de ng-repeatun número definido de veces en lugar de tener que iterar sobre una matriz?

Por ejemplo, a continuación quiero que el elemento de la lista se muestre 5 veces, suponiendo que sea $scope.numberigual a 5, además de incrementar el número para que cada elemento de la lista se incremente como 1, 2, 3, 4, 5

Resultado deseado:

<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>
Malcr001
fuente

Respuestas:

569

Actualización (25/09/2018)

Las versiones más recientes de AngularJS (> = 1.3.0) le permiten hacer esto solo con una variable (no se necesita ninguna función):

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

Esto no era posible en el momento en que se hizo la pregunta por primera vez. Gracias a @Nikhil Nambiar por su respuesta a continuación para esta actualización


Original (29/05/2013)

Por el momento, ng-repeatsolo acepta una colección como parámetro, pero puede hacer esto:

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

Y en algún lugar de tu controlador:

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

Esto le permitirá cambiar $scope.numbera cualquier número que desee y aún así mantener el enlace que está buscando.

EDITAR (1/6/2014) - Las versiones más nuevas de AngularJS (> = 1.1.5) requieren track by $index:

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

Aquí hay un violín con un par de listas que usan la misma getNumberfunción.

Dan
fuente
Estoy usando esto para varios elementos de la lista, pero solo parece funcionar para la primera lista. ¿Sabes por qué este es el caso?
Malcr001
Debería funcionar para cualquier cantidad de listas. Mira este violín
Dan
1
Gracias de nuevo. Olvidé eliminar ng-repeat en el elemento padre. Está funcionando ahora. Gracias.
Malcr001
3
$ scope.getNumber = function (num) {var x = new Array (); para (var i = 0; i <num; i ++) {x.push (i + 1); } retorno x; } // usa esta función cuando el número cambia dinámicamente
Manavendher
1
@ sh0ber. Cuando necesito cambiar los elementos de la lista según el valor seleccionado en el menú desplegable de números. Primero probé tu función, cuando no funciona, la cambié a la anterior para actualizar el no. de elementos de la lista cuando se selecciona un número diferente en el menú desplegable. ¿Pueden verificar mi escenario usando su función?
Manavendher
135

Puedes hacerlo:

<div ng-repeat="i in [1, 2, 3, 4]">
  ...
</div>
akonsu
fuente
1
funcionó de maravilla, probado en Chrome v. 39.0.2171.95 (64 bits), FF v. 33.1.1 y Safari v. 8.0.2
Neara
Esto funciona perfectamente si lo está utilizando en un control de paginación donde todo lo que necesita es <li> <a href = "javascript :;" ng-click = "SelectPage ($ index)"> {{i}} </a> </li>
Rick
@AdityaMP, use esto para rangos en javascript stackoverflow.com/a/31989462/3160597
azerafati
1
Considere llamar al constructor de matrices para una matriz de longitud dinámica, como se indica en esta respuesta .
maxathousand
¿Qué pasa si tengo que repetir 120 veces? ¿Debo ir con [1,2,3 ... 120]?
Munkhdelger Tumenbayar
94

Aquí hay un ejemplo de cómo podría hacer esto. Tenga en cuenta que me inspiró un comentario en los documentos ng-repeat: http://jsfiddle.net/digitalzebra/wnWY6/

Tenga en cuenta la directiva ng-repeat:

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

Aquí está el controlador:

function TestCtrl($scope) {
    $scope.range = function(n) {
        return new Array(n);
    };
};
Polaris878
fuente
8
También puede usar el _.rangesubrayado o lodash para crear la matriz: $ scope.range = _.range (0, n);
tarde
83

Creo que este jsFiddle de este hilo podría ser lo que estás buscando.

<div ng-app ng-controller="Main">
   <div ng-repeat="item in items | limitTo:2">
       {{item.name}}
   </div>
</div>
jeffmayeur
fuente
3
lea más abajo en el enlace del hilo de google y describe cómo puede usar 'slice'. ej. group1: items.slice (0,3), group2: items.slice (3,6), etc.
trevorc
77
Esta respuesta dará como resultado una huella mínima en sus controladores y creo que también es el enfoque angular preferido. La respuesta aceptada por la OMI debe ser reemplazada por esta.
Matt Jensen el
1
Esta debería ser la respuesta aceptada (en mi opinión): la más elegante, la más preferida.
Cody
11
@Cody Desafortunadamente, no, no responde la pregunta. OP dice "en lugar de tener que iterar siempre sobre una matriz" y "suponiendo que sea $scope.numberigual a 5". La intención era usar una variable entera para definir el recuento de elementos, no codificarlo y no usar una matriz predefinida.
Dan
55
@Cody @ sh0ber puede establecer el límite en su alcance ( $scope.limit = 2) y usarlo como ...|limitTo:limit- ver violín actualizado
drzaus
58

Un enfoque más simple sería (por ejemplo, 5 veces):

<div ng-repeat="x in [].constructor(5) track by $index">
       ...
</div>
Nikhil Nambiar
fuente
55
Brillante. Funciones legibles, cortas y nada tontas en el controlador para devolver una nueva matriz.
maxathousand
2
Amo de esta manera.
Rabino Shuki Gur
Votado, esto no fue posible cuando se hizo la pregunta por primera vez (Angular 1.2). Modifiqué la respuesta aceptada para incluir esto. ¡Buen trabajo!
Dan
1
Solo desearía entender por qué esta sintaxis funciona pero no Array(5)(o de hecho [...Array(5).keys()]para obtener una matriz [0,1,2,3,4])
Dylan Nicholson
50

Me encontré con el mismo problema. Encontré este hilo, pero no me gustaron los métodos que tenían aquí. Mi solución estaba usando underscore.js, que ya habíamos instalado. Es tan simple como esto:

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

Esto hará exactamente lo que estás buscando.

Mark Roach
fuente
27
Esto es bueno, pero tenga en cuenta que el subrayado no está dentro del alcance de forma predeterminada: no podría usarlo en su vista HTML sin hacer algo como eso $scope._ = _.
jedd.ahyoung
66
Si está usando lodash o guión bajo, debe ponerlo $rootScopepara que pueda usarse en todas partes. Ponga esto en su app.runfunción justo después de app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Jeremy Moritz
Esta fue una respuesta perfecta para mí. Es simple y muy directo. Como estaba repitiendo usando una variable que tenía un conteo, tuve que hacer ng-repeat = "n en _.range (1, count + 1). Gracias por la solución.
Darryl
Intenté esto y mientras _ aparece en $ rootScope, ng-repeat no muestra nada.
Paul
49

Quería mantener mi html muy mínimo, así que definí un pequeño filtro que crea la matriz [0,1,2, ...] como lo han hecho otros:

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

Después de eso, en la vista es posible usar así:

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

Esto es realmente feo, pero funciona sin un controlador para un entero o una variable:

entero:

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

variable:

<span ng-repeat="_ in ((_ = []) && (_.length=myVar) && _) track by $index">{{$index}}</span>
MJ
fuente
El mejor hack de todos! Gracias
Jannis
2
_ in (_ = []).length = 33; _ track by $indexun poco más pequeño
Fabricio
16

Hay muchas maneras de hacer esto. Estaba realmente molesto por tener la lógica en mi controlador, así que creé una directiva simple para resolver el problema de repetir un elemento n veces.

Instalación:

La directiva se puede instalar usando bower install angular-repeat-n

Ejemplo:

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

produce: 1234

También funciona usando una variable de alcance:

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

Fuente:

Github

connorbode
fuente
1
Esto es algo que deberían considerar agregar a las directivas angulares oficiales
HarshaXsoad
13

Esta es solo una ligera variación en la respuesta aceptada, pero realmente no necesita crear una nueva función. Solo para importar 'Array' en el alcance:

<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;
});

Vea este violín para un ejemplo en vivo.

Sylvain Leroux
fuente
44
actualizado (2016) y mucho más limpio!
Julien Malige
9

Respuesta más fácil: 2 líneas de código

JS (en su controlador AngularJS)

$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>

... donde repeatCountestá el número de repeticiones que deberían aparecer en esta ubicación.

JellicleCat
fuente
1
Creo que esto no le permite cambiar el número de repeticiones en el HTML si se cambia en el controlador, a menos que lo ajuste en una función como lo han hecho otras respuestas.
trysis
@trysis: no estoy seguro si entiendo su problema, pero debe reemplazarlo repeatCountcon un número real en el HTML, y siempre que ese número sea menor o igual a MAX_REPEATS, esto le permitirá establecer el número de repeticiones en el HTML.
JellicleCat
1
En mi opinión, esta es la forma más elegante de limitar la ngRepeatdirectiva. El uso de Array.prototype.sliceJS idiomático siempre se debe elegir sobre una biblioteca como underscore.js (dependiendo de la compatibilidad del navegador).
Pat Migliaccio
No es una mala solución, +1, pero creo que esta respuesta es más fácil y evita el desorden en el controlador.
maxathousand
8

angular proporciona una función muy dulce llamada corte ... con esto puedes lograr lo que estás buscando. por ejemplo, ng-repeat = "ab en abc.slice (startIndex, endIndex)"

esta demostración: http://jsfiddle.net/sahilosheal/LurcV/39/ lo ayudará y le dirá cómo usar esta función de "facilitar la vida". :)

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'}];
    }
sheelpriy
fuente
6

Heres una respuesta para angular 1.2.x

Básicamente es lo mismo, con la ligera modificación de ng-repeat

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

Aquí está el violín: http://jsfiddle.net/cHQLH/153/

Esto se debe a que angular 1.2 no permite valores duplicados en la directiva. Esto significa que si está intentando hacer lo siguiente, recibirá un error.

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

Puedes usar la ng-ifdirectiva conng-repeat

Entonces, si num es el número de veces que necesita repetir el elemento:

<li ng-repeat="item in list" ng-if="$index < num">
akaashanky
fuente
1
Para aquellos de ustedes a quienes les gusta el marcado limpio ... Tenga en cuenta que el uso ng-repeatde esta manera aún generará sus etiquetas comentadas ( <!-- ngIf: $index < num -->etc.). Simplemente no habrá lielementos para que el DOM los represente. Marque una "fuente de vista" en el panel de resultados aquí para ver a qué me refiero.
3

Puedes usar este ejemplo.

Controlador interno:

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

Ejemplo para seleccionar elemento en el lado del código HTML:

<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>
elceka
fuente
3

Para los usuarios que usan CoffeeScript, puede usar una comprensión de rango:

Directiva

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

o controlador

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

Modelo

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

Ampliando un poco la primera respuesta de Ivan, puede usar una cadena como la colección sin una pista por enunciado siempre que los caracteres sean únicos, por lo que si el caso de uso es menor a 10 números, esa es la pregunta que simplemente haría :

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

Lo cual es un poco jenky, claro, pero lo suficientemente simple para mirar y no particularmente confuso.

omikes
fuente
2

Primero, cree un filtro angular usando LoDash:

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

La función de tiempos de LoDash es capaz de manejar nulos, indefinidos, 0, números y cadenas de representación de números.

Luego, úsalo en tu HTML como esto:

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

o

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

Necesitaba una solución más dinámica para esto, donde podría incrementar la repetición.

HTML

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

Control de duplicador

<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)
}
adswebwork
fuente
1

Angular proporciona filtros para modificar una colección. En este caso, la colección sería nula, es decir, [], y el filtro también toma argumentos, como sigue:

<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;
}]);

Este método es muy similar a los propuestos anteriormente y no es necesariamente superior, pero muestra el poder de los filtros en AngularJS.

Nik Dow
fuente
1

Si n no es demasiado alto, otra opción podría ser dividir ('') con una cadena de n caracteres:

<div ng-controller="MainCtrl">
<div ng-repeat="a in 'abcdefgh'.split('')">{{$index}}</div>
</div>
vonwolf
fuente
Creo que la división es innecesaria aquí. una cadena ya es una matriz de caracteres.
omikes
1

Encontré el mismo problema y esto es con lo que salí:

(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();
    }
  }
})();

... y el html:

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

EJEMPLO EN VIVO

Usé la timesfunción de subrayado ya que ya la estábamos usando en el proyecto, pero puede reemplazarla fácilmente con código nativo.

nicooga
fuente
0

Estoy creando una directiva reutilizable donde el número máximo vendrá de otra ng-repeat. Entonces, esta es una edición sobre la respuesta mejor votada.

Simplemente cambie el código en el controlador a esto:

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

Esto devolverá una nueva matriz con un número especificado de iteraciones

sagars01
fuente
0

dado que iterar sobre una cadena representará un elemento para cada carácter:

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

Podemos usar esta solución fea pero sin código usando el number|n decimal placesfiltro nativo.

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

de esta manera tendremos mynumberelementos sin código extra. Decir '0.000'.
Usamos mynumber - 2para compensar 0.
No funcionará para números inferiores a 3, pero podría ser útil en algunos casos.

Ivan Ferrer Villa
fuente
usaste track by $index?
Ivan Ferrer Villa
este es el ghetto af. si va a verse obligado a tener un personaje para cada iteración, también podría hacerlong-repeat="i in [1,2,3,4]"
Roi
por supuesto, pero OP quiere que la iteración sea n veces basada en una variable$scope.number
Ivan Ferrer Villa
¿por qué no 'abcd' en lugar de 'aaaa' y luego descartar la pista?
omikes
aaaafue un ejemplo para explicar mi solución no muy elegante. Usando 'aaaa' o 'abcd' codificados, obtienes una lista de longitud fija, pero agregando mynumber-2decimales a 0, obtienes una 'cadena' con mynumbercaracteres. Digamos mynumber=5, lo entiendes '0.000', luego iteramos usando $ index
Ivan Ferrer Villa
0
$scope.number = 5;

<div ng-repeat="n in [] | range:$scope.number">
      <span>{{$index}}</span>
</div>
DuFuS
fuente
-1

manera simple:

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

en el componente / controlador y luego:

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

Este código es de mi proyecto de mecanografía, pero podría reorganizarse a JavaScript puro

Palepassion
fuente