Modo di ripetere ng di volte definito invece di ripetere su array?


417

C'è un modo per ng-repeatun numero definito di volte invece di dover sempre scorrere su un array?

Ad esempio, di seguito desidero che l'elemento dell'elenco venga visualizzato 5 volte assumendo $scope.numberuguale a 5 oltre ad aumentare il numero in modo che ciascun elemento dell'elenco aumenti come 1, 2, 3, 4, 5

Risultato desiderato:

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


Risposte:


569

Aggiornamento (25/09/2018)

Le versioni più recenti di AngularJS (> = 1.3.0) consentono di farlo con una sola variabile (nessuna funzione necessaria):

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

Questo non era possibile al momento della prima domanda. Ringraziamo @ Nikhil Nambiar dalla sua risposta di seguito per questo aggiornamento


Originale (29/05/2013)

Al momento, ng-repeataccetta solo una raccolta come parametro, ma puoi farlo:

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

E da qualche parte nel controller:

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

Ciò ti consentirebbe di modificare $scope.numberqualsiasi numero come desideri e mantenere comunque l'associazione che stai cercando.

EDIT (1/6/2014) - Le versioni più recenti di AngularJS (> = 1.1.5) richiedono track by $index:

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

Ecco un violino con un paio di liste usando la stessa getNumberfunzione.


Sto usando questo per più voci di elenco ma sembra funzionare solo per il primo elenco. Sai perché è così?
Malcr001,

Dovrebbe funzionare per qualsiasi numero di elenchi. Controllare questo violino
Dan

1
Grazie ancora. Ho dimenticato di rimuovere ng-repeat sull'elemento genitore. Sta lavorando adesso. Grazie.
Malcr001,

3
$ scope.getNumber = function (num) {var x = new Array (); per (var i = 0; i <num; i ++) {x.push (i + 1); } restituisce x; } // usa questa funzione quando il numero cambia in modo dinamico
Manavendher

1
@ sh0ber. Quando devo modificare le voci dell'elenco in base al valore selezionato nel menu a discesa dei numeri. Ho provato prima la tua funzione, quando non funziona, l'ho cambiata in sopra per aggiornare il no. di voci di elenco quando è selezionato un numero diverso nell'elenco a discesa. Potete per favore controllare il mio scenario usando la vostra funzione.
Manavendher,

135

Puoi farlo:

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

1
ha funzionato come un fascino, testato su Chrome v. 39.0.2171.95 (64 bit), FF v. 33.1.1 e Safari v. 8.0.2
Neara

Funziona perfettamente se lo si utilizza in un controllo di paginazione in cui tutto ciò che serve è <li> <a href = "javascript :;" ng-click = "SelectPage ($ index)"> {{i}} </a> </li>
Rick,

@AdityaMP, utilizzare questo per gli intervalli in javascript stackoverflow.com/a/31989462/3160597
azerafati

1
Prendi in considerazione la possibilità di chiamare il costruttore della matrice per una matrice a lunghezza dinamica, come indicato in questa risposta .
maxathous

cosa succede se devo ripetere 120 volte. Dovrei andare con [1,2,3 ... 120]?
Munkhdelger Tumenbayar,

94

Ecco un esempio di come potresti farlo. Nota che sono stato ispirato da un commento nei documenti ng-repeat: http://jsfiddle.net/digitalzebra/wnWY6/

Nota la direttiva ng-repeat:

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

Ecco il controller:

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

8
È inoltre possibile utilizzare _.rangeda Underscore o lodash per creare l'array: $ scope.range = _.range (0, n);
pomeriggio

83

Penso che questo jsFiddle da questo thread potrebbe essere quello che stai cercando.

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

3
leggi più in basso sul link del thread di Google e descrive come puoi usare 'slice'. ad es. gruppo1: items.slice (0,3), group2: items.slice (3,6), ecc.
trevorc

7
Questa risposta comporterà il minimo ingombro nei controller e credo sia anche l'approccio angolare preferito. La risposta accettata dall'IMO dovrebbe essere sostituita con questa.
Matt Jensen,

1
Questa dovrebbe essere la risposta accettata (secondo me): la più elegante, la più preferita.
Cody,

11
@Cody Purtroppo no, non risponde alla domanda. Gli stati OP "invece di dover sempre scorrere su un array" e "assumendo $scope.numberuguale a 5". L'intento era di utilizzare una variabile intera per definire il conteggio degli articoli, non codificarlo e non utilizzare un array predefinito.
Dan,

5
@Cody @ sh0ber puoi impostare il limite nel tuo ambito ( $scope.limit = 2) e usarlo come ...|limitTo:limit- vedi violino aggiornato
drzaus

58

Un approccio più semplice sarebbe (per un esempio di 5 volte):

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

5
Brillante. Funzioni leggibili, brevi e assurde nel controller per restituire un nuovo array.
maxathous

2
Adoro così.
Rabbi Shuki Gur,

Sottovalutato, ciò non è stato possibile alla prima domanda (Angolare 1.2). Ho modificato la risposta accettata per includerla. Bel lavoro!
Dan,

1
Vorrei solo capire perché questa sintassi funziona ma non Array(5)(o addirittura [...Array(5).keys()]ottenere un array [0,1,2,3,4])
Dylan Nicholson

50

Ho riscontrato lo stesso problema. Mi sono imbattuto in questo thread, ma non mi sono piaciuti i metodi che avevano qui. La mia soluzione stava usando underscore.js, che avevamo già installato. È semplice come questo:

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

Questo farà esattamente quello che stai cercando.


27
Questo è buono, ma tieni presente che Underscore non rientra nell'ambito di default - non saresti in grado di usarlo nella tua vista HTML senza fare qualcosa del genere $scope._ = _.
jedd.ahyoung,

6
Se stai usando lodash o underscore, dovresti metterlo in $rootScopemodo che possa essere usato ovunque. Metti questo nella tua app.runfunzione subito dopo app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Jeremy Moritz l'

Questa è stata una risposta perfetta per me. È semplice e molto diretto. Poiché stavo ripetendo usando una variabile che aveva un conteggio, dovevo fare ng-repeat = "n in _.range (1, count + 1). Grazie per la soluzione.
Darryl

Ho provato questo e mentre _ appare in $ rootScope, ng-repeat non rende nulla.
Paul,

49

Volevo mantenere il mio HTML molto minimale, così ho definito un piccolo filtro che crea l'array [0,1,2, ...] come altri hanno fatto:

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

Successivamente, sulla vista è possibile utilizzare in questo modo:

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

34

Questo è davvero brutto, ma funziona senza un controller per un numero intero o una variabile:

numero intero:

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

variabile:

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

Il miglior hack di sempre! Grazie
jannis l'

2
_ in (_ = []).length = 33; _ track by $indexleggermente più piccolo
Fabricio

16

Ci sono molti modi per farlo. Ero davvero infastidito dall'avere la logica nel mio controller, quindi ho creato una semplice direttiva per risolvere il problema di ripetere un elemento n-volte.

Installazione:

La direttiva può essere installata utilizzando bower install angular-repeat-n

Esempio:

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

produce: 1234

Funziona anche usando una variabile scope:

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

Fonte:

Github


1
Questo è qualcosa che dovrebbero considerare di aggiungere alle direttive angolari ufficiali
HarshaXsoad,

13

Questa è solo una leggera variazione sulla risposta accettata, ma non è necessario creare una nuova funzione. Solo per importare "Array" nell'ambito:

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

Vedi questo violino per un esempio dal vivo.


4
aggiornato (2016) e molto più pulito!
Julien Malige,

9

Risposta più semplice: 2 righe di codice

JS (nel controller 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>

... dov'è repeatCountil numero di ripetizioni che dovrebbero apparire in questa posizione.


1
Credo che questo non ti permetta di cambiare il numero di ripetizioni nell'HTML se è cambiato nel controller, a meno che non lo avvolgi in una funzione come hanno fatto altre risposte.
trysis,

@trysis: non sono sicuro di aver compreso il tuo problema, ma dovresti sostituirlo repeatCountcon un numero effettivo nell'HTML e fintanto che quel numero è inferiore o uguale a MAX_REPEATS, questo ti permetterà di impostare il numero di ripetizioni in HTML.
JellicleCat

1
A mio avviso, questo è il modo più elegante di limitare la ngRepeatdirettiva. L'uso di Array.prototype.sliceJS idiomatico e sempre dovrebbe essere scelto su una libreria come underscore.js (la compatibilità del browser dipende).
Pat Migliaccio,

Non è una cattiva soluzione, +1, ma penso che questa risposta sia più semplice ed eviti di ingombrare il controller.
maxathous

8

angular dà una funzione molto dolce chiamata slice .. usando questo puoi ottenere quello che stai cercando. ad es. ng-repeat = "ab in abc.slice (startIndex, endIndex)"

questa demo: http://jsfiddle.net/sahilosheal/LurcV/39/ ti aiuterà e ti dirà come usare questa funzione "rendere la vita 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'}];
    }

6

Ecco una risposta per 1.2.x angolare

Fondamentalmente è lo stesso, con la leggera modifica di ng-repeat

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

ecco il violino: http://jsfiddle.net/cHQLH/153/

questo perché l'angolare 1.2 non consente valori duplicati nella direttiva. Questo significa che se stai provando a fare quanto segue, otterrai un errore.

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

6

È possibile utilizzare la ng-ifdirettiva conng-repeat

Quindi, se num è il numero di volte in cui è necessario ripetere l'elemento:

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

1
Per quelli a cui piace il markup pulito ... Tenere presente che l'utilizzo ng-repeatin questo modo produrrà comunque tag commentati ( <!-- ngIf: $index < num -->ecc.). Semplicemente non ci saranno lielementi per il rendering del DOM. Controlla una "vista sorgente" nel riquadro dei risultati qui per vedere cosa intendo.

3

Puoi usare questo esempio.

Controller interno:

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

Esempio per l'elemento select sul lato del codice 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>

3

Per gli utenti che utilizzano CoffeeScript, è possibile utilizzare una comprensione dell'intervallo:

Direttiva

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

o controller

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

Modello

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

3

Espandendo un po 'la prima risposta di Ivan un po', puoi usare una stringa come raccolta senza una traccia per istruzione fintanto che i caratteri sono unici, quindi se il caso d'uso è inferiore a 10 numeri come è la domanda che farei semplicemente :

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

Che è un po 'ingenuo, certo, ma abbastanza semplice da guardare e non particolarmente confuso.


2

Innanzitutto, crea un filtro angolare usando LoDash:

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

La funzione tempi LoDash è in grado di gestire valori null, non definiti, 0, numeri e stringhe di numeri.

Quindi, usalo nel tuo HTML come questo:

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

o

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

1

Avevo bisogno di una soluzione più dinamica a questo - dove potevo incrementare la ripetizione.

HTML

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

Controllo duplicatore

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

1

Angular fornisce filtri per modificare una raccolta. In questo caso la raccolta sarebbe nulla, vale a dire [], e il filtro accetta anche argomenti, come segue:

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

Questo metodo è molto simile a quelli proposti sopra e non è necessariamente superiore ma mostra la potenza dei filtri in AngularJS.


1

Se n non è troppo alto, un'altra opzione potrebbe essere quella di utilizzare split ('') con una stringa di n caratteri:

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

credo che la divisione non sia necessaria qui. una stringa è già una matrice di caratteri.
omike

1

Ho riscontrato lo stesso problema e questo è quello con cui sono uscito:

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

... e l'html:

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

ESEMPIO LIVE

Ho usato la timesfunzione di trattino basso come già in uso sul progetto, ma puoi facilmente sostituirla con un codice nativo.


0

Sto creando una direttiva riutilizzabile in cui il numero massimo verrà da un'altra ng-repeat. Quindi, questa è una modifica rispetto alla risposta più votata.

Basta cambiare il codice sul controller in questo -

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

Ciò restituirà un nuovo array con il numero specificato di iterazioni


0

poiché iterando su una stringa renderà un elemento per ogni carattere:

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

possiamo usare questa brutta soluzione ma senza codice usando il number|n decimal placesfiltro nativo.

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

in questo modo avremo mynumberelementi senza codice aggiuntivo. Say '0.000'.
Usiamo mynumber - 2per compensare 0.
Non funzionerà con numeri inferiori a 3, ma potrebbe essere utile in alcuni casi.


hai usato track by $index?
Ivan Ferrer Villa,

questo è ghetto af. se sarai costretto ad avere un carattere per ogni iterazione che potresti fareng-repeat="i in [1,2,3,4]"
Roi,

certo, ma OP vuole che l'iterazione sia n volte basata su una variabile$scope.number
Ivan Ferrer Villa

perché non 'abcd' invece di 'aaaa' e quindi trascinare la traccia?
omike

aaaaè stato un esempio per spiegare la mia soluzione non molto elegante. Usando 'aaaa' o 'abcd' hardcoded ottieni un elenco di lunghezza fissa, ma aggiungendo i mynumber-2decimali a 0, ottieni una 'stringa' con mynumbercaratteri. Supponiamo mynumber=5che '0.000'lo ripetiamo usando $ index
Ivan Ferrer Villa il

0
$scope.number = 5;

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

-1

modo semplice:

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

nel componente / controller e quindi:

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

Questo codice proviene dal mio progetto dattiloscritto ma potrebbe essere riorganizzato in javascript puro

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.