Möglichkeit, die definierte Anzahl von Wiederholungen zu wiederholen, anstatt sie über das Array zu wiederholen?

417

Gibt es eine Möglichkeit, ng-repeateine definierte Anzahl von Malen festzulegen, anstatt immer über ein Array iterieren zu müssen?

Im Folgenden möchte ich beispielsweise, dass das Listenelement fünfmal angezeigt wird, wobei angenommen wird $scope.number, dass es zusätzlich zu der Anzahl gleich 5 ist, sodass jedes Listenelement wie 1, 2, 3, 4, 5 inkrementiert

Erwünschtes Ergebnis:

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

Antworten:

569

Update (25.09.2008)

In neueren Versionen von AngularJS (> = 1.3.0) können Sie dies nur mit einer Variablen tun (keine Funktion erforderlich):

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

Dies war zum Zeitpunkt der ersten Frage nicht möglich. Dank an @Nikhil Nambiar aus seiner Antwort unten für dieses Update


Original (29.05.2013)

Im Moment ng-repeatakzeptiert nur eine Sammlung als Parameter, aber Sie können dies tun:

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

Und irgendwo in Ihrem Controller:

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

Auf diese Weise können Sie nach Belieben $scope.numberzu einer beliebigen Nummer wechseln und die gesuchte Bindung beibehalten.

BEARBEITEN (06.01.2014) - Neuere Versionen von AngularJS (> = 1.1.5) erfordern track by $index:

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

Hier ist eine Geige mit ein paar Listen, die dieselbe getNumberFunktion verwenden.

Dan
quelle
Ich verwende dies für mehrere Listenelemente, aber es scheint nur für die erste Liste zu funktionieren. Wissen Sie, warum dies der Fall ist?
Malcr001
Es sollte für eine beliebige Anzahl von Listen funktionieren. Überprüfen Sie diese Geige
Dan
1
Danke noch einmal. Ich habe vergessen, ng-repeat für das übergeordnete Element zu entfernen. Es funktioniert jetzt. Vielen Dank.
Malcr001
3
$ scope.getNumber = function (num) {var x = new Array (); für (var i = 0; i <num; i ++) {x.push (i + 1); } return x; } // benutze diese Funktion, wenn sich die Zahl dynamisch ändert
Manavendher
1
@ sh0ber. Wenn ich die Listenelemente basierend auf dem in der Nummern-Dropdown-Liste ausgewählten Wert ändern muss. Ich habe zuerst Ihre Funktion ausprobiert. Wenn sie nicht funktioniert, habe ich sie in oben geändert, um die Nr. Zu aktualisieren. von Listenelementen, wenn in der Dropdown-Liste eine andere Nummer ausgewählt ist. Können Sie bitte mein Szenario mit Ihrer Funktion überprüfen.
Manavendher
135

du kannst das:

<div ng-repeat="i in [1, 2, 3, 4]">
  ...
</div>
Akonsu
quelle
1
funktionierte wie ein Zauber, getestet auf Chrome v. 39.0.2171.95 (64-Bit), FF v. 33.1.1 und Safari v. 8.0.2
Neara
Dies funktioniert perfekt, wenn Sie es in einem Paginierungssteuerelement verwenden, in dem Sie lediglich <li> <a href = "javascript:;" ng-click = "SelectPage ($ index)"> {{i}} </a> </ li>
Rick
@AdityaMP, verwenden Sie dies für Bereiche in Javascript stackoverflow.com/a/31989462/3160597
azerafati
1
Rufen Sie den Array-Konstruktor für ein Array mit dynamischer Länge auf, wie in dieser Antwort angegeben .
Maxathousand
Was ist, wenn ich 120 Mal wiederholen muss? Soll ich mit [1,2,3 ... 120] gehen?
Munkhdelger Tumenbayar
94

Hier ist ein Beispiel, wie Sie dies tun können. Beachten Sie, dass ich von einem Kommentar in den ng-repeat-Dokumenten inspiriert wurde: http://jsfiddle.net/digitalzebra/wnWY6/

Beachten Sie die ng-repeat-Direktive:

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

Hier ist der Controller:

function TestCtrl($scope) {
    $scope.range = function(n) {
        return new Array(n);
    };
};
Polaris878
quelle
8
Sie können _.rangedas Array auch mit Underscore oder lodash erstellen: $ scope.range = _.range (0, n);
Nachmittag
83

Ich denke, diese jsFiddle aus diesem Thread könnte das sein, wonach Sie suchen.

<div ng-app ng-controller="Main">
   <div ng-repeat="item in items | limitTo:2">
       {{item.name}}
   </div>
</div>
jeffmayeur
quelle
3
Lesen Sie weiter unten auf dem Google Thread-Link, und es wird beschrieben, wie Sie "Slice" verwenden können. zB Gruppe1: items.slice (0,3), group2: items.slice (3,6) usw.
trevorc
7
Diese Antwort führt zu einem möglichst geringen Platzbedarf in Ihren Controllern, und ich glaube, dies ist auch der bevorzugte Angular-Ansatz. Die von der IMO akzeptierte Antwort sollte durch diese ersetzt werden.
Matt Jensen
1
Dies sollte die akzeptierte Antwort sein (meiner Meinung nach) - Am elegantesten, am meisten bevorzugt.
Cody
11
@Cody Leider nein, es beantwortet die Frage nicht. OP gibt an, "anstatt immer über ein Array iterieren zu müssen" und " $scope.numbergleich 5 anzunehmen ". Die Absicht war, eine Ganzzahlvariable zu verwenden, um die Anzahl der Elemente zu definieren, sie nicht fest zu codieren und kein vordefiniertes Array zu verwenden.
Dan
5
@Cody @ sh0ber Sie können das Limit in Ihrem Bereich ( $scope.limit = 2) setzen und es verwenden wie ...|limitTo:limit- siehe aktualisierte Geige
drzaus
58

Ein einfacherer Ansatz wäre (für ein Beispiel von 5 Mal):

<div ng-repeat="x in [].constructor(5) track by $index">
       ...
</div>
Nikhil Nambiar
quelle
5
Brillant. Lesbare, kurze und keine dummen Funktionen in der Steuerung, um ein neues Array zurückzugeben.
Maxathousand
2
Ich liebe diesen Weg.
Rabbi Shuki Gur
Upvoted war dies nicht möglich, als die Frage zum ersten Mal gestellt wurde (Angular 1.2). Ich habe die akzeptierte Antwort geändert, um dies einzuschließen. Gut gemacht!
Dan
1
Ich wünschte nur, ich hätte verstanden, warum diese Syntax funktioniert, aber nicht Array(5)(oder um tatsächlich [...Array(5).keys()]ein Array [0,1,2,3,4] zu erhalten)
Dylan Nicholson
50

Ich bin auf dasselbe Problem gestoßen. Ich bin auf diesen Thread gestoßen, mochte aber nicht die Methoden, die sie hier hatten. Meine Lösung war die Verwendung von underscore.js, die wir bereits installiert hatten. So einfach ist das:

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

Dies wird genau das tun, wonach Sie suchen.

Mark Roach
quelle
27
Dies ist gut, aber beachten Sie, dass der Unterstrich standardmäßig nicht im Geltungsbereich liegt. Sie könnten ihn nicht in Ihrer HTML-Ansicht verwenden, ohne so etwas zu tun $scope._ = _.
jedd.ahyoung
6
Wenn Sie lodash oder Unterstrich verwenden, sollten Sie es einfügen, $rootScopedamit es überall verwendet werden kann. Setzen Sie dies in Ihre app.runFunktion kurz nach dem app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Jeremy Moritz
Dies war eine perfekte Antwort für mich. Es ist einfach und sehr unkompliziert. Da ich mit einer Variablen wiederholte, die eine Zählung hatte, musste ich ng-repeat = "n in _.range (1, count + 1) ausführen. Danke für die Lösung.
Darryl
Ich habe es versucht und während _ in $ rootScope angezeigt wird, rendert die ng-Wiederholung nichts.
Paul
49

Ich wollte mein HTML sehr minimal halten, also definierte ich einen kleinen Filter, der das Array [0,1,2, ...] wie andere erstellt:

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

Danach kann die Ansicht folgendermaßen verwendet werden:

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

Das ist wirklich hässlich, aber es funktioniert ohne Controller für eine Ganzzahl oder eine Variable:

ganze Zahl:

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

Variable:

<span ng-repeat="_ in ((_ = []) && (_.length=myVar) && _) track by $index">{{$index}}</span>
MJ
quelle
Bester Hack aller Zeiten! Danke
jannis
2
_ in (_ = []).length = 33; _ track by $indexetwas kleiner
Fabricio
16

Es gibt viele Möglichkeiten, dies zu tun. Ich war wirklich besorgt darüber, die Logik in meinem Controller zu haben, also habe ich eine einfache Anweisung erstellt, um das Problem der n-fachen Wiederholung eines Elements zu lösen.

Installation:

Die Direktive kann mit installiert werden bower install angular-repeat-n

Beispiel:

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

produziert: 1234

Es funktioniert auch mit einer Bereichsvariablen:

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

Quelle:

Github

Connorbode
quelle
1
Dies ist etwas, das sie in Betracht ziehen sollten, um offizielle Winkelanweisungen hinzuzufügen
HarshaXsoad
13

Dies ist nur eine geringfügige Abweichung von der akzeptierten Antwort, aber Sie müssen keine neue Funktion erstellen . Nur um 'Array' in den Bereich zu importieren:

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

Sehen Sie sich diese Geige als Live-Beispiel an.

Sylvain Leroux
quelle
4
aktuell (2016) und viel sauberer!
Julien Malige
9

Einfachste Antwort: 2 Codezeilen

JS (in Ihrem 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>

... wo repeatCountist die Anzahl der Wiederholungen, die an dieser Stelle erscheinen sollen.

JellicleCat
quelle
1
Ich glaube, dies erlaubt Ihnen nicht, die Anzahl der Wiederholungen im HTML zu ändern, wenn es im Controller geändert wird, es sei denn, Sie wickeln es in eine Funktion ein, wie es andere Antworten getan haben.
Tryse
@trysis: Ich bin mir nicht sicher, ob ich Ihr Problem verstehe, aber Sie sollten es durch repeatCounteine tatsächliche Zahl im HTML ersetzen. Solange diese Zahl kleiner oder gleich ist MAX_REPEATS, können Sie die Zahl festlegen von Wiederholungen im HTML.
JellicleCat
1
Meiner Meinung nach ist dies die eleganteste Art, die ngRepeatRichtlinie einzuschränken . Verwenden Array.prototype.sliceund idiomatisches JS sollte immer einer Bibliothek wie underscore.js vorgezogen werden (je nach Browserkompatibilität).
Pat Migliaccio
Keine schlechte Lösung, +1, aber ich denke, diese Antwort ist einfacher und vermeidet Unordnung im Controller.
Maxathousand
8

eckig gibt eine sehr süße Funktion namens Scheibe . Mit dieser können Sie erreichen, was Sie suchen. zB ng-repeat = "ab in abc.slice (startIndex, endIndex)"

Diese Demo: http://jsfiddle.net/sahilosheal/LurcV/39/ hilft Ihnen dabei und erklärt Ihnen, wie Sie diese Funktion "Das Leben leichter machen" verwenden können. :) :)

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

Hier ist eine Antwort für Winkel 1.2.x.

Grundsätzlich ist es das gleiche, mit der geringfügigen Änderung der ng-repeat

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

Hier ist die Geige: http://jsfiddle.net/cHQLH/153/

Dies liegt daran, dass Winkel 1.2 keine doppelten Werte in der Direktive zulässt. Dies bedeutet, dass Sie eine Fehlermeldung erhalten, wenn Sie Folgendes versuchen.

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

Du kannst den ... benutzen ng-if Direktive mit verwendenng-repeat

Wenn also num die Häufigkeit ist, mit der das Element wiederholt werden muss:

<li ng-repeat="item in list" ng-if="$index < num">
akaashanky
quelle
1
Für diejenigen unter Ihnen, die sauberes Markup mögen ... Denken Sie daran, dass die Verwendung ng-repeatauf diese Weise weiterhin die kommentierten Tags ( <!-- ngIf: $index < num -->usw.) ausgibt . Es gibt einfach keine liElemente, die das DOM rendern kann. Überprüfen Sie hier im Ergebnisbereich eine "Ansichtsquelle", um zu sehen, was ich meine.
3

Sie können dieses Beispiel verwenden.

Innerhalb des Controllers:

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

Beispiel für ein Auswahlelement auf der HTML-Codeseite:

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

Für Benutzer, die CoffeeScript verwenden, können Sie ein Bereichsverständnis verwenden:

Richtlinie

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

oder Controller

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

Vorlage

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

Wenn Sie die erste Antwort von Ivan ein wenig erweitern, können Sie einen String als Sammlung ohne Track-by-Anweisung verwenden, solange die Zeichen eindeutig sind. Wenn der Anwendungsfall also weniger als 10 Zahlen umfasst, wie ich es einfach tun würde ::

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

Das ist ein bisschen ruckelig, sicher, aber einfach genug anzusehen und nicht besonders verwirrend.

Omikes
quelle
2

Erstellen Sie zunächst mit LoDash einen Winkelfilter:

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

Die LoDash-Zeitfunktion kann null, undefiniert, 0, Zahlen und Zeichenfolgendarstellung von Zahlen verarbeiten.

Verwenden Sie es dann in Ihrem HTML wie folgt:

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

oder

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

Ich brauchte eine dynamischere Lösung dafür - wo ich die Wiederholung erhöhen konnte.

HTML

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

Duplikatorsteuerung

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

Angular bietet Filter zum Ändern einer Sammlung. In diesem Fall wäre die Auflistung null, dh [], und der Filter akzeptiert auch folgende Argumente:

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

Diese Methode ist den oben vorgeschlagenen sehr ähnlich und nicht unbedingt überlegen, zeigt jedoch die Leistung von Filtern in AngularJS.

Nik Dow
quelle
1

Wenn n nicht zu hoch ist, kann eine andere Option darin bestehen, split ('') mit einer Zeichenfolge von n Zeichen zu verwenden:

<div ng-controller="MainCtrl">
<div ng-repeat="a in 'abcdefgh'.split('')">{{$index}}</div>
</div>
vonwolf
quelle
Ich glaube, die Trennung ist hier unnötig. Eine Zeichenfolge ist bereits ein Array von Zeichen.
Omikes
1

Ich bin auf dasselbe Problem gestoßen und habe Folgendes herausgefunden:

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

... und das HTML:

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

LIVE BEISPIEL

Ich habe die timesFunktion des Unterstrichs verwendet, da wir sie bereits im Projekt verwendet haben, aber Sie können sie leicht durch nativen Code ersetzen.

Nicooga
quelle
0

Ich erstelle eine wiederverwendbare Direktive, bei der die maximale Anzahl aus einer anderen ng-Wiederholung stammt. Dies ist also eine Bearbeitung der am besten bewerteten Antwort.

Ändern Sie einfach den Code am Controller in diesen -

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

Dies gibt ein neues Array mit der angegebenen Anzahl von Iterationen zurück

sagars01
quelle
0

Da es über eine Zeichenfolge iteriert, wird für jedes Zeichen ein Element gerendert:

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

Wir können diese hässliche Problemumgehung ohne Code mithilfe des number|n decimal placesnativen Filters verwenden.

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

Auf diese Weise haben wir mynumberElemente ohne zusätzlichen Code. Sagen Sie '0.000'.
Wir verwenden mynumber - 2, um zu kompensieren. 0.
Es funktioniert nicht für Zahlen unter 3, kann aber in einigen Fällen nützlich sein.

Ivan Ferrer Villa
quelle
haben Sie verwendet track by $index?
Ivan Ferrer Villa
das ist ghetto af. Wenn Sie gezwungen sein werden, für jede Iteration ein ng-repeat="i in [1,2,3,4]"
Roi
Natürlich, aber OP möchte, dass die Iteration n-mal basierend auf einer Variablen erfolgt$scope.number
Ivan Ferrer Villa
warum nicht 'abcd' statt 'aaaa' und dann den Track vorbeischaben?
Omikes
aaaawar ein Beispiel, um meine - nicht sehr elegante - Problemumgehung zu erklären. Wenn Sie 'aaaa' oder 'abcd' fest codieren, erhalten Sie eine Liste mit fester Länge. Wenn Sie jedoch mynumber-2Dezimalstellen zu 0 hinzufügen , erhalten Sie eine 'Zeichenfolge' mit mynumberZeichen. Sagen wir mynumber=5, Sie bekommen '0.000', dann wiederholen wir das mit $ index
Ivan Ferrer Villa
0
$scope.number = 5;

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

einfacher Weg:

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

in der Komponente / Steuerung und dann:

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

Dieser Code stammt aus meinem Typoskript-Projekt, könnte aber in reines Javascript umgewandelt werden

Pallepassion
quelle