Manière de ng-répéter un nombre défini de fois au lieu de répéter sur le tableau?

417

Existe-t-il un moyen d'effectuer ng-repeatun nombre défini de fois au lieu de toujours avoir à parcourir un tableau?

Par exemple, ci-dessous, je veux que l'élément de liste apparaisse 5 fois en supposant $scope.numberégal à 5 ​​en plus incrémentant le nombre de sorte que chaque élément de liste incrémente comme 1, 2, 3, 4, 5

Résultat désiré:

<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
la source

Réponses:

569

Mise à jour (25/09/2018)

Les nouvelles versions d'AngularJS (> = 1.3.0) vous permettent de le faire avec seulement une variable (aucune fonction nécessaire):

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

Cela n'était pas possible au moment où la question a été posée pour la première fois. Nous remercions @Nikhil Nambiar de sa réponse ci-dessous pour cette mise à jour


Original (29/05/2013)

Pour le moment, ng-repeatn'accepte qu'une collection comme paramètre, mais vous pouvez le faire:

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

Et quelque part dans votre contrôleur:

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

Cela vous permettrait de modifier $scope.numbern'importe quel nombre à votre guise et de conserver la liaison que vous recherchez.

EDIT (1/6/2014) - Les nouvelles versions d'AngularJS (> = 1.1.5) nécessitent track by $index:

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

Voici un violon avec quelques listes utilisant la même getNumberfonction.

Dan
la source
J'utilise ceci pour plusieurs éléments de liste, mais cela ne semble fonctionner que pour la première liste. Savez-vous pourquoi c'est le cas?
Malcr001
Cela devrait fonctionner pour n'importe quel nombre de listes. Vérifiez ce violon
Dan
1
Merci encore. J'ai oublié de supprimer ng-repeat sur l'élément parent. Ça marche maintenant. Merci.
Malcr001
3
$ scope.getNumber = function (num) {var x = new Array (); pour (var i = 0; i <num; i ++) {x.push (i + 1); } return x; } // utilise cette fonction lorsque le nombre change dynamiquement
Manavendher
1
@ sh0ber. Lorsque je dois modifier les éléments de la liste en fonction de la valeur sélectionnée dans la liste déroulante des nombres. J'ai essayé votre fonction en premier, quand elle ne fonctionne pas, je l'ai changée en dessus pour mettre à jour le no. des éléments de la liste lorsqu'un numéro différent est sélectionné dans la liste déroulante. Pouvez-vous s'il vous plaît vérifier mon scénario en utilisant votre fonction.
Manavendher
135

tu peux le faire:

<div ng-repeat="i in [1, 2, 3, 4]">
  ...
</div>
akonsu
la source
1
fonctionnait comme un charme, testé sur Chrome v. 39.0.2171.95 (64 bits), FF v. 33.1.1 et Safari v. 8.0.2
Neara
Cela fonctionne parfaitement si vous l'utilisez dans un contrôle de pagination où tout ce dont vous avez besoin est <li> <a href = "javascript :;" ng-click = "SelectPage ($ index)"> {{i}} </a> </li>
Rick
@AdityaMP, utilisez ceci pour les plages dans javascript stackoverflow.com/a/31989462/3160597
azerafati
1
Envisagez d'appeler le constructeur de tableau pour un tableau de longueur dynamique, comme indiqué dans cette réponse .
maxathousand
et si je dois répéter 120 fois. Dois-je aller avec [1,2,3 ... 120]?
Munkhdelger Tumenbayar
94

Voici un exemple de la façon dont vous pouvez le faire. Notez que j'ai été inspiré par un commentaire dans les documents ng-repeat: http://jsfiddle.net/digitalzebra/wnWY6/

Notez la directive ng-repeat:

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

Voici le contrôleur:

function TestCtrl($scope) {
    $scope.range = function(n) {
        return new Array(n);
    };
};
Polaris878
la source
8
Vous pouvez également utiliser _.rangeUnderscore ou lodash pour créer le tableau: $ scope.range = _.range (0, n);
après
83

Je pense que ce jsFiddle de ce fil pourrait être ce que vous cherchez.

<div ng-app ng-controller="Main">
   <div ng-repeat="item in items | limitTo:2">
       {{item.name}}
   </div>
</div>
jeffmayeur
la source
3
lire plus loin sur le lien de fil Google et il décrit comment vous pouvez utiliser "tranche". par exemple groupe1: items.slice (0,3), groupe2: items.slice (3,6), etc.
trevorc
7
Cette réponse se traduira par l'empreinte la plus minimale dans vos contrôleurs et je crois que c'est l'approche angulaire préférée également. La réponse acceptée par l'OMI devrait être remplacée par celle-ci.
Matt Jensen
1
Cela devrait être la réponse acceptée (à mon avis) - La plus élégante, la plus préférée.
Cody
11
@Cody Malheureusement, non cela ne répond pas à la question. OP indique "au lieu de toujours avoir à répéter sur un tableau" et "en supposant $scope.numberégal à 5". L'intention était d'utiliser une variable entière pour définir le nombre d'éléments, pas de le coder en dur et de ne pas utiliser un tableau prédéfini.
Dan
5
@Cody @ sh0ber vous pouvez définir la limite dans votre portée ( $scope.limit = 2) et l'utiliser comme ...|limitTo:limit- voir violon mis à jour
drzaus
58

Une approche plus simple serait (pour un exemple de 5 fois):

<div ng-repeat="x in [].constructor(5) track by $index">
       ...
</div>
Nikhil Nambiar
la source
5
Brillant. Fonctions lisibles, courtes et sans idiot dans le contrôleur pour renvoyer un nouveau tableau.
maxathousand
2
J'aime cette façon.
Rabbi Shuki Gur
Voté, cela n'a pas été possible lors de la première question (Angular 1.2). J'ai modifié la réponse acceptée pour l'inclure. Bon travail!
Dan
1
Je souhaite juste avoir compris pourquoi cette syntaxe fonctionne mais pas Array(5)(ou bien [...Array(5).keys()]obtenir un tableau [0,1,2,3,4])
Dylan Nicholson
50

J'ai rencontré le même problème. Je suis tombé sur ce fil, mais je n'ai pas aimé les méthodes qu'ils avaient ici. Ma solution utilisait underscore.js, que nous avions déjà installé. C'est aussi simple que ça:

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

Cela fera exactement ce que vous recherchez.

Mark Roach
la source
27
C'est bien, mais notez que Underscore n'est pas dans la portée par défaut - vous ne pourriez pas l'utiliser dans votre vue HTML sans faire quelque chose comme $scope._ = _.
jedd.ahyoung
6
Si vous utilisez du lodash ou du trait de soulignement, vous devez le mettre $rootScopepour qu'il puisse être utilisé partout. Mettez ceci dans votre app.runfonction juste après app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Jeremy Moritz
C'était une réponse parfaite pour moi. C'est simple et très simple. Comme je répétais en utilisant une variable qui avait un compte, j'ai dû faire ng-repeat = "n dans _.range (1, count + 1). Merci pour la solution.
Darryl
J'ai essayé cela et tandis que _ apparaît dans $ rootScope, le ng-repeat ne rend rien.
Paul
49

Je voulais garder mon html très minimal, j'ai donc défini un petit filtre qui crée le tableau [0,1,2, ...] comme d'autres l'ont fait:

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

Après cela, sur la vue est possible d'utiliser comme ceci:

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

C'est vraiment Moche, mais cela fonctionne sans contrôleur pour un entier ou une variable:

entier:

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

variable:

<span ng-repeat="_ in ((_ = []) && (_.length=myVar) && _) track by $index">{{$index}}</span>
MJ
la source
Meilleur hack jamais! Merci
jannis
2
_ in (_ = []).length = 33; _ track by $indexlégèrement plus petit
Fabricio
16

Il y a plusieurs façons de procéder. J'étais vraiment gêné d'avoir la logique dans mon contrôleur, j'ai donc créé une directive simple pour résoudre le problème de la répétition d'un élément n fois.

Installation:

La directive peut être installée en utilisant bower install angular-repeat-n

Exemple:

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

produit: 1234

Il fonctionne également à l'aide d'une variable de portée:

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

La source:

Github

connorbode
la source
1
C'est quelque chose qu'ils devraient envisager d'ajouter aux directives angulaires officielles
HarshaXsoad
13

Ce n'est qu'une légère variation de la réponse acceptée, mais vous n'avez pas vraiment besoin de créer une nouvelle fonction. Uniquement pour importer 'Array' dans la portée:

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

Voir ce violon pour un exemple en direct.

Sylvain Leroux
la source
4
à jour (2016) et beaucoup plus propre!
Julien Malige
9

Réponse la plus simple: 2 lignes de code

JS (dans votre contrôleur 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>

... où repeatCountest le nombre de répétitions qui devraient apparaître à cet endroit.

JellicleCat
la source
1
Je crois que cela ne vous permet pas de changer le nombre de répétitions dans le HTML s'il est modifié dans le contrôleur, à moins que vous ne l'enveloppiez dans une fonction comme l'ont fait d'autres réponses.
trysis
@trysis: je ne sais pas si je comprends votre problème, mais vous devez le remplacer repeatCountpar un nombre réel dans le code HTML, et tant que ce nombre est inférieur ou égal à MAX_REPEATS, cela vous permettra de définir le nombre de répétitions dans le HTML.
JellicleCat
1
À mon avis, c'est la manière la plus élégante de limiter la ngRepeatdirective. L'utilisation de Array.prototype.sliceJS idiomatique et doit toujours être choisie sur une bibliothèque comme underscore.js (selon la compatibilité du navigateur).
Pat Migliaccio
Pas une mauvaise solution, +1, mais je pense que cette réponse est plus facile et évite d'encombrer le contrôleur.
maxathousand
8

angulaire donne une fonction très douce appelée tranche .. en utilisant cela, vous pouvez réaliser ce que vous recherchez. par exemple ng-repeat = "ab dans abc.slice (startIndex, endIndex)"

cette démo: http://jsfiddle.net/sahilosheal/LurcV/39/ vous aidera et vous expliquera comment utiliser cette fonction "rendre la vie facile". :)

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
la source
6

Voici une réponse pour 1.2.x angulaire

Fondamentalement, c'est la même chose, avec la légère modification de la ng-repeat

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

voici le violon: http://jsfiddle.net/cHQLH/153/

En effet, angular 1.2 n'autorise pas les valeurs en double dans la directive. Cela signifie que si vous essayez de faire ce qui suit, vous obtiendrez une erreur.

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

Vous pouvez utiliser la ng-ifdirective avecng-repeat

Donc, si num est le nombre de fois où l'élément doit être répété:

<li ng-repeat="item in list" ng-if="$index < num">
akaashanky
la source
1
Pour ceux d'entre vous qui aiment le balisage propre ... Gardez à l'esprit que l'utilisation ng-repeatde cette manière produira toujours ses balises commentées ( <!-- ngIf: $index < num -->etc.). Il n'y aura tout simplement aucun liélément à rendre par le DOM. Vérifiez une "source d'affichage" dans le volet des résultats ici pour voir ce que je veux dire.
3

Vous pouvez utiliser cet exemple.

Contrôleur intérieur:

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

Exemple d'élément select du côté du code 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
la source
3

Pour les utilisateurs utilisant CoffeeScript, vous pouvez utiliser une compréhension de plage:

Directif

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

ou contrôleur

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

Modèle

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

En développant un peu la première réponse d'Ivan, vous pouvez utiliser une chaîne comme collection sans instruction track by tant que les caractères sont uniques, donc si le cas d'utilisation est inférieur à 10 chiffres, comme c'est la question que je ferais simplement :

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

Ce qui est un peu jenky, bien sûr, mais assez simple à regarder et pas particulièrement déroutant.

omikes
la source
2

Créez d'abord un filtre angulaire à l'aide de LoDash:

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

La fonction de temps LoDash est capable de gérer des représentations nulles, non définies, 0, des nombres et des chaînes de nombres.

Ensuite, utilisez-le dans votre HTML comme ceci:

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

ou

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

J'avais besoin d'une solution plus dynamique à cela - où je pourrais incrémenter la répétition.

HTML

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

Contrôle du duplicateur

<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
la source
1

Angular fournit des filtres pour modifier une collection. Dans ce cas, la collection serait nulle, c'est-à-dire [], et le filtre prend également des arguments, comme suit:

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

Cette méthode est très similaire à celles proposées ci-dessus et n'est pas nécessairement supérieure mais montre la puissance des filtres dans AngularJS.

Nik Dow
la source
1

Si n n'est pas trop élevé, une autre option pourrait être d'utiliser split ('') avec une chaîne de n caractères:

<div ng-controller="MainCtrl">
<div ng-repeat="a in 'abcdefgh'.split('')">{{$index}}</div>
</div>
vonwolf
la source
je crois que la scission n'est pas nécessaire ici. une chaîne est déjà un tableau de caractères.
omikes
1

J'ai rencontré le même problème et voici ce avec quoi je suis sorti:

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

... et le html:

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

EXEMPLE EN DIRECT

J'ai utilisé la timesfonction de soulignement car nous l'utilisions déjà sur le projet, mais vous pouvez facilement la remplacer par du code natif.

nicooga
la source
0

Je crée une directive réutilisable où le nombre maximum proviendra d'une autre répétition ng. Il s'agit donc d'une modification de la meilleure réponse votée.

Changez simplement le code du contrôleur en ceci -

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

Cela renverra un nouveau tableau avec un nombre spécifié d'itérations

sagars01
la source
0

puisque l'itération sur une chaîne, il rendra un élément pour chaque caractère:

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

nous pouvons utiliser cette solution de contournement laide mais sans code en utilisant le number|n decimal placesfiltre natif.

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

de cette façon, nous aurons des mynumberéléments sans code supplémentaire. Dis '0.000'.
Nous utilisons mynumber - 2pour compenser 0.
Cela ne fonctionnera pas pour les nombres inférieurs à 3, mais pourrait être utile dans certains cas.

Villa Ivan Ferrer
la source
as-tu utilisé track by $index?
Ivan Ferrer Villa
c'est ghetto af. si vous allez être obligé d'avoir un caractère pour chaque itération, vous pourriez aussi bien le faireng-repeat="i in [1,2,3,4]"
Roi
bien sûr, mais OP veut que l'itération soit n fois basée sur une variable$scope.number
Ivan Ferrer Villa
pourquoi ne pas «abcd» au lieu de «aaaa» et ensuite supprimer la piste?
omikes
aaaaétait un exemple pour expliquer ma solution de contournement - pas très élégante -. En utilisant «aaaa» ou «abcd» codé en dur, vous obtenez une liste de longueur fixe, mais en ajoutant des mynumber-2décimales à 0, vous obtenez une «chaîne» avec des mynumbercaractères. Dites mynumber=5, vous obtenez '0.000', puis nous répétons cela en utilisant $ index
Ivan Ferrer Villa
0
$scope.number = 5;

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

manière simple:

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

dans le composant / contrôleur puis:

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

Ce code provient de mon projet dactylographié mais pourrait être réorganisé en javascript pur

Pallepassion
la source