Sposób na powtórzenie zdefiniowanej liczby razy zamiast powtarzania przez tablicę?


417

Czy jest na to sposób ng-repeat określoną liczbę razy zamiast konieczności iteracji po tablicy?

Na przykład poniżej chcę, aby element listy pojawił się 5 razy, przy założeniu, że jest $scope.numberrówny 5 dodatkowo zwiększając liczbę, więc każdy element listy zwiększa się o 1, 2, 3, 4, 5

Pożądany rezultat:

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


Odpowiedzi:


569

Aktualizacja (25.09.2018)

Nowsze wersje AngularJS (> = 1.3.0) pozwalają to zrobić tylko ze zmienną (żadna funkcja nie jest wymagana):

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

Nie było to możliwe w momencie pierwszego pytania. Podziękowania dla @Nikhil Nambiar z jego odpowiedzi poniżej dla tej aktualizacji


Oryginał (29.05.2013)

W tej chwili ng-repeatakceptuje tylko kolekcję jako parametr, ale możesz to zrobić:

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

I gdzieś w twoim kontrolerze:

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

Pozwoliłoby to na zmianę $scope.numberdowolnej liczby i utrzymanie wiązania, którego szukasz.

EDYCJA (1/6/2014) - Nowsze wersje AngularJS (> = 1.1.5) wymagają track by $index:

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

Oto skrzypce z kilkoma listami używającymi tej samej getNumberfunkcji.


Używam tego do wielu elementów listy, ale wydaje się, że działa tylko dla pierwszej listy. Czy wiesz, dlaczego tak jest?
Malcr001

Powinien działać na dowolnej liczbie list. Sprawdź to skrzypce
Dan

1
Dzięki jeszcze raz. Zapomniałem usunąć ng-repeat z elementu nadrzędnego. Już działa. Dzięki.
Malcr001

3
$ scope.getNumber = function (num) {var x = new Array (); dla (var i = 0; i <num; i ++) {x.push (i + 1); } return x; } // użyj tej funkcji, gdy liczba zmienia się dynamicznie
Manavendher

1
@ sh0ber. Kiedy muszę zmienić elementy listy na podstawie wartości wybranej w rozwijanym numerze. Najpierw wypróbowałem twoją funkcję, kiedy nie działa, zmieniłem ją na powyższą, aby zaktualizować nie. elementów listy, gdy w rozwijanym menu wybrano inną liczbę. Czy możesz sprawdzić mój scenariusz za pomocą swojej funkcji.
Manavendher

135

możesz to zrobić:

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

1
działał jak urok, testowany na Chrome v. 39.0.2171.95 (64-bit), FF v. 33.1.1 i Safari v. 8.0.2
Neara

Działa to doskonale, jeśli używasz go w kontrolce paginacji, gdzie wszystko czego potrzebujesz to <li> <a href = "javascript :;" ng-click = "SelectPage ($ index)"> {{i}} </a> </li>
Rick

@AdityaMP, użyj tego dla zakresów w javascript stackoverflow.com/a/31989462/3160597
azerafati

1
Rozważ wywołanie konstruktora tablicy dla tablicy o dynamicznej długości, jak podano w tej odpowiedzi .
maxathousand

co jeśli muszę powtórzyć 120 razy. Czy powinienem wybrać [1,2,3 ... 120]?
Munkhdelger Tumenbayar

94

Oto przykład, jak możesz to zrobić. Zauważ, że zainspirował mnie komentarz w dokumentacji powtórzeń ng: http://jsfiddle.net/digitalzebra/wnWY6/

Zwróć uwagę na dyrektywę ng-repeat:

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

Oto kontroler:

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

8
Możesz także użyć _.rangeUnderscore lub lodash, aby utworzyć tablicę: $ scope.range = _.range (0, n);
po południu

83

Myślę, że ten jsFiddle z tego wątku może być tym, czego szukasz.

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

3
czytaj dalej link do wątku Google, który opisuje, jak możesz używać „wycinka”. np. grupa 1: przedmioty. skórka (0,3), grupa 2: przedmioty. skórka (3,6) itd.
trevorc

7
Ta odpowiedź spowoduje jak najmniejsze obciążenie twoich kontrolerów i uważam, że jest to również preferowane podejście Angular. Odpowiedź IMO powinna zostać zastąpiona tym.
Matt Jensen

1
To powinna być zaakceptowana odpowiedź (moim zdaniem) - najbardziej elegancka, najbardziej preferowana na ng.
Cody

11
@Cody Niestety nie, to nie odpowiada na pytanie. OP stwierdza „zamiast zawsze iterować po tablicy” i „zakładając, że $scope.numberwynosi 5”. Chodziło o to, aby użyć zmiennej liczby całkowitej do zdefiniowania liczby elementów, nie kodować jej na stałe i nie używać predefiniowanej tablicy.
Dan

5
@Cody @ sh0ber możesz ustawić limit w swoim zakresie ( $scope.limit = 2) i używać go jak ...|limitTo:limit- patrz zaktualizowane skrzypce
drzaus

58

Prostsze podejście byłoby (na przykład 5 razy):

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

5
Znakomity. Czytelne, krótkie i niemądre funkcje w kontrolerze, aby zwrócić nową tablicę.
maxathousand

2
Kocham w ten sposób.
Rabin Shuki Gur,

W głosowaniu nie było to możliwe, gdy pytanie zostało zadane po raz pierwszy (Angular 1.2). Zmodyfikowałem zaakceptowaną odpowiedź, aby uwzględnić to. Dobra robota!
Dan

1
Chciałbym tylko zrozumieć, dlaczego ta składnia działa, ale nie Array(5)((a nawet [...Array(5).keys()]uzyskać tablicę [0,1,2,3,4])
Dylan Nicholson

50

Natrafiłem na ten sam problem. Natknąłem się na ten wątek, ale nie podobały mi się metody, które tu zastosowali. Moje rozwiązanie wykorzystywało underscore.js, które już zainstalowaliśmy. To takie proste:

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

To zrobi dokładnie to, czego szukasz.


27
To dobrze, ale zwróć uwagę, że podkreślenie nie jest domyślnie objęte zakresem - nie można go używać w widoku HTML bez robienia czegoś takiego $scope._ = _.
jedd.ahyoung

6
Jeśli używasz lodash lub podkreślnika, powinieneś go umieścić, $rootScopeaby można go było używać wszędzie. Umieść to w swojej app.runfunkcji zaraz po app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Jeremy Moritz

To była dla mnie idealna odpowiedź. To proste i bardzo proste. Ponieważ powtarzałem za pomocą zmiennej, która miała liczbę, musiałem wykonać ng-repeat = "n w _.range (1, count + 1). Dzięki za rozwiązanie.
Darryl

Próbowałem tego i podczas gdy _ pojawia się w $ rootScope, powtórzenie ng nic nie renderuje.
Paul

49

Chciałem, aby mój html był bardzo minimalny, dlatego zdefiniowałem mały filtr, który tworzy tablicę [0,1,2, ...] tak jak zrobili to inni:

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

Następnie w widoku można używać w następujący sposób:

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

34

To jest naprawdę Brzydkie, ale działa bez kontrolera dla liczby całkowitej lub zmiennej:

liczba całkowita:

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

zmienna:

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

Najlepszy hack w historii! Dzięki
jannis,

2
_ in (_ = []).length = 33; _ track by $indexnieco mniejszy
Fabricio

16

Istnieje wiele sposobów, aby to zrobić. Naprawdę martwiłem się logiką w moim kontrolerze, dlatego stworzyłem prostą dyrektywę, aby rozwiązać problem powtarzania elementu n-razy.

Instalacja:

Dyrektywę można zainstalować za pomocą bower install angular-repeat-n

Przykład:

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

produkuje: 1234

Działa również przy użyciu zmiennej scope:

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

Źródło:

Github


1
To jest coś, co powinni rozważyć dodanie do oficjalnych dyrektyw kątowych
HarshaXsoad

13

To tylko niewielka odmiana zaakceptowanej odpowiedzi, ale tak naprawdę nie trzeba tworzyć nowej funkcji. Aby zaimportować „Array” w zakresie:

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

Zobacz to skrzypce, aby zobaczyć przykład na żywo.


4
aktualne (2016) i dużo czystsze!
Julien Malige,

9

Najłatwiejsza odpowiedź: 2 linie kodu

JS (w twoim kontrolerze 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>

... gdzie repeatCountjest liczba powtórzeń, które powinny pojawić się w tej lokalizacji.


1
Uważam, że nie pozwala to na zmianę liczby powtórzeń w kodzie HTML, jeśli zostanie ona zmieniona w kontrolerze, chyba że zostanie ona zawinięta w funkcję, tak jak zrobiły to inne odpowiedzi.
trysis

@trysis: Nie jestem pewien, czy rozumiem twój problem, ale powinieneś zastąpić repeatCountgo rzeczywistą liczbą w kodzie HTML, i dopóki ta liczba będzie mniejsza lub równa MAX_REPEATS, pozwoli ci to ustawić liczbę powtórzeń w HTML.
JellicleCat

1
Moim zdaniem jest to najbardziej elegancki sposób ograniczenia ngRepeatdyrektywy. Używanie Array.prototype.slicei idiomatyczny JS powinien być zawsze wybierany nad biblioteką taką jak underscore.js (zależnie od kompatybilności przeglądarki).
Pat Migliaccio,

Nie jest to złe rozwiązanie, +1, ale myślę, że ta odpowiedź jest łatwiejsza i pozwala uniknąć zaśmiecania kontrolera.
maxathousand

8

kątowy daje bardzo słodką funkcję zwaną plasterkiem . Dzięki temu możesz osiągnąć to, czego szukasz. np. ng-repeat = "ab in abc.slice (startIndex, endIndex)"

to demo: http://jsfiddle.net/sahilosheal/LurcV/39/ pomoże ci powiedzieć, jak korzystać z tej funkcji „ułatwiającej życie”. :)

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

Oto odpowiedź na pytanie kątowe 1.2.x

Zasadniczo jest to to samo, z niewielką modyfikacją ng-repeat

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

oto skrzypce: http://jsfiddle.net/cHQLH/153/

Wynika to z faktu, że kątowy 1.2 nie zezwala na powielanie wartości w dyrektywie. Oznacza to, że jeśli próbujesz wykonać następujące czynności, pojawi się błąd.

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

6

Możesz użyć ng-ifdyrektywy zng-repeat

Jeśli więc liczba jest liczbą powtórzeń elementu:

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

1
Dla tych, którzy lubią czyste znaczniki ... Pamiętaj, że użycie ng-repeatw ten sposób nadal będzie generować komentarze z tagami ( <!-- ngIf: $index < num -->itp.). Po prostu nie będzie żadnych lielementów do renderowania DOM. Sprawdź „wyświetl źródło” w okienku wyników tutaj, aby zobaczyć, co mam na myśli.

3

Możesz użyć tego przykładu.

Wewnątrz kontrolera:

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

Przykład dla elementu select po stronie kodu 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

Użytkownicy korzystający z CoffeeScript mogą korzystać ze zrozumienia zakresu:

Dyrektywa

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

lub kontroler

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

Szablon

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

3

Rozwijając nieco pierwszą odpowiedź Ivana, możesz użyć łańcucha jako kolekcji bez ścieżki według instrukcji, pod warunkiem, że znaki są unikalne, więc jeśli przypadek użycia jest mniejszy niż 10 liczb, to jest pytanie, które po prostu zrobiłbym :

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

Co jest nieco zakłopotane, jasne, ale wystarczająco proste, aby na nie patrzeć i niezbyt mylące.


2

Najpierw utwórz filtr kątowy za pomocą LoDash:

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

Funkcja czasów LoDash jest w stanie obsłużyć null, niezdefiniowane, 0, liczby i ciąg znaków reprezentujący liczby.

Następnie użyj go w swoim HTML jako:

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

lub

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

1

Potrzebowałem bardziej dynamicznego rozwiązania tego problemu - w którym mógłbym zwiększyć liczbę powtórzeń.

HTML

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

Kontrola powielacza

<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 zapewnia filtry do modyfikowania kolekcji. W takim przypadku kolekcja byłaby pusta, tj. [], A filtr przyjmuje również następujące argumenty:

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

Ta metoda jest bardzo podobna do tych zaproponowanych powyżej i niekoniecznie jest lepsza, ale pokazuje moc filtrów w AngularJS.


1

Jeśli n nie jest zbyt wysokie, inną opcją może być użycie split ('') z ciągiem n znaków:

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

uważam, że podział jest tutaj niepotrzebny. ciąg jest już tablicą znaków.
omikes

1

Zetknąłem się z tym samym problemem i właśnie z tego wyszło:

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

... i HTML:

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

PRZYKŁAD NA ŻYWO

Użyłem timesfunkcji podkreślenia, ponieważ używaliśmy jej już w projekcie, ale można ją łatwo zastąpić rodzimym kodem.


0

Tworzę dyrektywę wielokrotnego użytku, w której maksymalna liczba będzie pochodzić z innego powtórzenia ng. To jest edycja najlepszej odpowiedzi.

Po prostu zmień kod na kontrolerze na to -

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

Zwróci to nową tablicę z określoną liczbą iteracji


0

ponieważ iteracja po ciągu spowoduje wyświetlenie elementu dla każdego znaku:

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

możemy użyć tego brzydkiego, ale bez kodu obejścia, używając number|n decimal placesfiltru natywnego.

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

w ten sposób będziemy mieć mynumberelementy bez dodatkowego kodu. Powiedzmy '0.000'.
Używamy mynumber - 2do kompensacji. 0.
To nie działa dla liczb poniżej 3, ale może być przydatne w niektórych przypadkach.


używałeś track by $index?
Ivan Ferrer Villa

to jest getto af. jeśli będziesz zmuszony mieć char dla każdej iteracji, równie dobrze możesz to zrobićng-repeat="i in [1,2,3,4]"
Roi

oczywiście, ale OP chce, aby iteracja była n razy na podstawie zmiennej$scope.number
Ivan Ferrer Villa

dlaczego nie „abcd” zamiast „aaaa”, a następnie zeskrobać ścieżkę?
omikes

aaaabył przykładem wyjaśniającym moje - nie bardzo eleganckie - obejście. Używając na stałe „aaaa” lub „abcd”, otrzymujesz listę o stałej długości, ale dodając miejsca po mynumber-2przecinku do 0, otrzymujesz „ciąg znaków” z mynumberznakami. Powiedzmy mynumber=5, rozumiemy '0.000', a następnie iterujemy to za pomocą indeksu $
Ivan Ferrer Villa

0
$scope.number = 5;

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

-1

prosta droga:

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

w komponencie / kontrolerze, a następnie:

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

Ten kod pochodzi z mojego projektu maszynopisu, ale można go przestawić na czysty JavaScript

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.