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>
Malcr001
źródło

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.

Dan
źródło
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>
akonsu
źródło
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);
    };
};
Polaris878
źródło
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>
jeffmayeur
źródło
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>
Nikhil Nambiar
źródło
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.

Mark Roach
źródło
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>
miguelr
źródło
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>
MJ
źródło
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

Connorbode
źródło
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.

Sylvain Leroux
źródło
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.

JellicleCat
źródło
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'}];
    }
Sheelpriy
źródło
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>
DrogoNevets
źródło
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">
akaashanky
źródło
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>
elceka
źródło
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>
Roi
źródło
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.

omikes
źródło
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>
Karanvir Kang
źródło
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)
}
sieć reklamowa
źródło
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.

Nik Dow
źródło
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>
vonwolf
źródło
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.

nicooga
źródło
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

sagars01
źródło
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.

Ivan Ferrer Villa
źródło
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>
DuFuS
źródło
-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

Pallepassion
źródło