Dizi üzerinde yineleme yapmak yerine tanımlı sayıda ng yineleme yolu?


417

İçin bir yol var mı ng-repeat zaman bir dizi üzerinden yineleme yapmak yerine belirli bir sayıda tanımlanmış ?

Örneğin, aşağıda liste öğesinin 5'e $scope.numbereşit olduğunu varsayarak 5 kez görünmesini istiyorum, böylece her liste öğesi 1, 2, 3, 4, 5

İstenen sonuç:

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


Yanıtlar:


569

Güncelleme (25.09.2018)

AngularJS'nin yeni sürümleri (> = 1.3.0) bunu yalnızca bir değişkenle yapmanıza izin verir (işlev gerekmez):

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

Sorunun ilk sorulduğu anda bu mümkün değildi. Bu güncelleme için aşağıdaki cevabından @Nikhil Nambiar'a teşekkür ederiz


Orijinal (29.05.2013)

Şu anda, ng-repeatbir koleksiyonu yalnızca parametre olarak kabul etmektedir, ancak bunu yapabilirsiniz:

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

Ve kumandanızda bir yerde:

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

Bu, değiştirmenize izin verir $scope.number gibi herhangi bir sayıya geçmenizi ve aradığınız bağlamayı korumanızı sağlar.

EDIT (1/6/2014) - AngularJS'nin daha yeni sürümleri (> = 1.1.5) track by $indexşunları gerektirir :

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

İşte aynı getNumberişlevi kullanan birkaç listeye sahip bir keman .


Bunu birden çok liste öğesi için kullanıyorum, ancak yalnızca ilk liste için çalışıyor gibi görünüyor. Neden böyle olduğunu biliyor musun?
Malcr001

Herhangi bir sayıda liste için çalışmalıdır. Bu kemanı
Dan

1
Tekrar teşekkürler. Üst öğedeki ng-yinesini kaldırmayı unuttum. Şuan çalışıyor. Teşekkürler.
Malcr001

3
$ scope.getNumber = function (num) {var x = new Array (); için (var i = 0; i <num; i ++) {x.push (i + 1); } dönüş x; } // sayı dinamik olarak değiştiğinde bu işlevi kullanın
Manavendher

1
@ sh0ber. Liste öğelerini sayı açılır menüsünde seçilen değere göre değiştirmem gerektiğinde. İlk önce işlevinizi denedim, çalışmadığında, no'yu güncellemek için yukarıdaki olarak değiştirdim. açılır listesinden farklı bir numara seçildiğinde liste öğelerinin listesi. Lütfen fonksiyonumu kullanarak senaryomu kontrol edebilir misin?
Manavendher

135

Bunu yapabilirsiniz:

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

1
bir çekicilik gibi çalıştı, Chrome v. 39.0.2171.95 (64 bit), FF v. 33.1.1 ve Safari v. 8.0.2
Neara

İhtiyacınız olan tek şeyin <li> <a href = "javascript :;" olduğu bir sayfalandırma denetiminde kullanıyorsanız, bu mükemmel çalışır. ng-click = "SelectPage ($ endeksi)"> {{i}} </a> </li>
Rick

@AdityaMP, javascript aralıkları için kullanacağız stackoverflow.com/a/31989462/3160597
azerafati

1
Bu cevapta belirtildiği gibi dizi yapıcısını dinamik uzunluktaki bir dizi için çağırmayı düşünün .
maxathousand

ne 120 kez tekrarlamak zorunda kalırsam. [1,2,3 ... 120] ile gitmeli miyim?
Munkhdelger Tumenbayar

94

İşte bunu nasıl yapabileceğinize bir örnek. Ng-tekrar belgelerindeki bir yorumdan ilham aldığımı unutmayın: http://jsfiddle.net/digitalzebra/wnWY6/

Ng-tekrar direktifine dikkat edin:

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

İşte denetleyici:

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

8
_.rangeAlt çizgi veya lodash dizisini oluşturmak için de kullanabilirsiniz : $ scope.range = _.range (0, n);
öğleden sonra

83

Bunu düşünmek jsFiddle bundan iplik aradığınız şey olabilir.

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

3
google thread bağlantısı hakkında daha fazla bilgi edindiğinizde, 'dilim'i nasıl kullanabileceğiniz açıklanmaktadır. ör. grup1: öğeler. dilim (0,3), grup2: öğeler. dilim (3,6), vb.
trevorc

7
Bu cevap denetleyicilerinizde en az yer kaplayacak ve ben de tercih edilen Açısal yaklaşım olduğuna inanıyorum. IMO tarafından kabul edilen cevap bununla değiştirilmelidir.
Matt Jensen

1
Bu kabul edilen cevap olmalı (bence) - En zarif, en çok tercih edilen.
Cody

11
@Cody Ne yazık ki, hayır soruya cevap vermiyor. OP "her zaman bir dizi üzerinden yineleme yapmak yerine" ve " $scope.number5'e eşit olduğu varsayılır" ifadesini kullanır. Amaç, öğe sayısını tanımlamak için bir tamsayı değişkeni kullanmaktı, sabit kodlamak değil, önceden tanımlanmış bir dizi kullanmak değildi.
Dan

5
@Cody @ sh0ber kapsamınızdaki sınırı ayarlayabilir ( $scope.limit = 2) ve aşağıdaki gibi kullanabilirsiniz ...|limitTo:limit- güncellenmiş keman görün
drzaus

58

Daha basit bir yaklaşım (5 kez bir örnek için):

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

5
Parlak. Yeni bir dizi döndürmek için denetleyicide okunabilir, kısa ve aptalca işlevler yok.
maxathousand

2
Bu şekilde seviyorum.
Rabbi Shuki Gur

Bu soruya ilk sorulduğunda bu mümkün değildi (Açısal 1.2). Kabul edilen cevabı, bunu içerecek şekilde değiştirdim. İyi iş!
Dan

1
Sadece bu sözdizimi çalışır ancak neden anladım dilek Array(5)(aslında ya [...Array(5).keys()]dizisini almak için [0,1,2,3,4])
Dylan Nicholson

50

Ben de aynı sorunla karşılaştım. Bu iş parçacığına rastladım, ama burada sahip oldukları yöntemleri beğenmedim. Çözümüm, önceden yüklediğimiz underscore.js'yi kullanmaktı. Bu kadar basit:

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

Bu tam olarak aradığınızı yapacak.


27
Bu iyidir, ancak Underscore'un varsayılan olarak kapsamda olmadığını unutmayın; HTML görünümünde böyle bir şey yapmadan kullanamazsınız $scope._ = _.
jedd.ahyoung

6
Lodash veya alt çizgi kullanıyorsanız, $rootScopeher yerde kullanılabilmesi için koymalısınız . Bunu app.runhemen ardından işlevinize koyun app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Jeremy Moritz

Bu benim için mükemmel bir cevaptı. Çok basit ve çok açık. Sayımı olan bir değişken kullanarak tekrarladığım için ng-repeat = "n in _.range (1, count + 1) 'i yapmak zorunda kaldım. Çözüm için teşekkürler.
Darryl

Bunu denedim ve _ $ rootScope'ta görünürken ng-repeat hiçbir şey yapmıyor.
Paul

49

Benim html çok az tutmak istedim, bu yüzden diğerleri gibi [0,1,2, ...] dizi oluşturan küçük bir filtre tanımladı:

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

Bundan sonra, görünümde böyle kullanmak mümkündür:

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

34

Bu gerçekten Çirkin, ama bir tamsayı veya değişken için kontrolör olmadan çalışır:

tamsayı:

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

değişken:

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

Şimdiye kadarki en iyi kesmek! Teşekkürler
jannis

2
_ in (_ = []).length = 33; _ track by $indexbiraz daha küçük
Fabricio

16

Bunu yapmanın birçok yolu var. Denetleyicimde mantığa sahip olmaktan gerçekten rahatsız oldum, bu yüzden bir öğeyi n kez tekrarlama sorununu çözmek için basit bir yönerge oluşturdum.

Kurulum:

Yönerge kullanılarak kurulabilir bower install angular-repeat-n

Misal:

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

üretir: 1234

Ayrıca bir kapsam değişkeni kullanarak da çalışır:

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

Kaynak:

Github


1
Bu, resmi açısal direktiflere eklemeyi düşünmeleri gereken bir şey
HarshaXsoad

13

Bu, kabul edilen cevapta sadece küçük bir varyasyon olmakla birlikte, yeni bir işlev oluşturmanız gerekmez . Yalnızca kapsamdaki 'Dizi'yi içe aktarmak için:

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

Canlı bir örnek için bu kemana bakın .


4
güncel (2016) ve çok daha temiz!
Julien Malige

9

En kolay cevap: 2 satır kod

JS (AngularJS kontrol cihazınızda)

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

... repeatCountbu konumda görünmesi gereken tekrar sayısı.


1
Bunun, diğer cevaplar gibi bir işlevde sarmadıkça, denetleyicide değiştirilirse HTML'deki tekrar sayısını değiştirmenize izin vermediğine inanıyorum.
trysis

@trysis: Sorununuzu anladığımdan emin değilim, ancak repeatCountHTML'deki gerçek bir sayı ile değiştirmelisiniz ve bu sayı eşit veya daha küçük olduğu sürece, bu numarayı MAX_REPEATSayarlamanıza izin verecektir HTML'deki tekrarların sayısı.
JellicleCat

1
Bana göre, bu ngRepeatdirektifi sınırlamanın en zarif yolu . Kullanarak Array.prototype.sliceve deyimsel JS her zaman underscore.js (tarayıcı uyumluluğuna bağlı olarak) gibi bir kütüphane üzerinden seçilmelidir.
Pat Migliaccio

Kötü bir çözüm değil, +1, ama bu cevabın daha kolay olduğunu düşünüyorum ve denetleyicinin dağınıklığını önler.
maxathousand

8

açısal dilim denilen çok tatlı bir fonksiyon verir .. bunu kullanarak aradığınızı elde edebilirsiniz. örneğin ng-repeat = "abc.slice ab (startIndex, endIndex)"

bu demo: http://jsfiddle.net/sahilosheal/LurcV/39/ size yardımcı olacak ve bu "hayatı kolaylaştırmak" işlevini nasıl kullanacağınızı anlatacaktır. :)

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

Heres açısal 1.2.x için bir cevap

Temelde aynıdır, hafif bir değişiklikle ng-repeat

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

İşte keman: http://jsfiddle.net/cHQLH/153/

bunun nedeni açısal 1.2'nin direktifte yinelenen değerlere izin vermemesidir. Bu, aşağıdakileri yapmaya çalışıyorsanız bir hata alacağınız anlamına gelir.

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

6

ng-ifYönerge ile birlikte kullanabilirsiniz.ng-repeat

Yani, num tekrarlanan öğeye kaç kez ihtiyacınız olduğunu gösterir:

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

1
Temiz biçimlendirmeyi sevenler için ... ng-repeatBu şekilde kullanmayı unutmayın , yine yorumlanmış etiketler ( <!-- ngIf: $index < num -->vb ..) çıktılar . liDOM'un oluşturması için herhangi bir öğe olmayacak . Ne demek istediğimi görmek için buradaki sonuçlar bölmesinde bir "kaynağı görüntüle" ye bakın.

3

Bu örneği kullanabilirsiniz.

İç denetleyici:

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

HTML kodu tarafındaki seçme öğesi için örnek:

<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

CoffeeScript kullanan kullanıcılar için bir dizi kavrama kullanabilirsiniz:

Direktif

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

veya Denetleyici

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

şablon

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

3

Ivan'ın ilk cevabına biraz biraz genişleyerek, karakterler benzersiz olduğu sürece, tek tek deyim olmadan koleksiyon olarak bir dize kullanabilirsiniz. :

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

Hangi biraz cenky, emin, ama bakmak ve özellikle kafa karıştırıcı kadar basit.


2

İlk olarak, LoDash kullanarak açısal bir filtre oluşturun:

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

LoDash süreleri işlevi null, undefined, 0, number ve sayıların dize olarak temsilini yapabilir.

Ardından, HTML'nizde şu şekilde kullanın:

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

veya

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

1

Bunun için daha dinamik bir çözüme ihtiyacım vardı.

HTML

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

Teksir Kontrolü

<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

Açısal, bir koleksiyonu değiştirmek için filtreler sağlar. Bu durumda, koleksiyon null olur, yani [] ve filtre de aşağıdaki gibi bağımsız değişkenler alır:

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

Bu yöntem yukarıda önerilenlere çok benzer ve mutlaka üstün değildir, ancak AngularJS'deki filtrelerin gücünü gösterir.


1

N çok yüksek değilse, başka bir seçenek n karakter dizesiyle split ('') kullanmak olabilir:

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

Bölünmenin gereksiz olduğuna inanıyorum. bir dize zaten bir karakter dizisidir.
omikes

1

Aynı sorunla karşılaştım ve bu ben ile çıktı:

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

... ve html:

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

CANLI ÖRNEK

Alt çizgi timesişlevini zaten projede kullandığımız gibi kullandım, ancak bunu yerel kodla kolayca değiştirebilirsiniz.


0

Maksimum sayının başka bir ng-tekrarından geleceği yeniden kullanılabilir bir yönerge oluşturuyorum. Yani, bu en iyi oylanan cevap üzerinde yapılan bir düzenlemedir.

Sadece denetleyicideki kodu değiştirin.

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

Bu, belirtilen sayıda yineleme içeren yeni bir dizi döndürür


0

bir dize üzerinden yinelendiği için her karakter için bir öğe oluşturur:

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

bu çirkin ama kodsuz geçici çözümü number|n decimal placesyerel filtreyi kullanarak kullanabiliriz .

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

bu şekilde mynumberekstra kod içermeyen öğelerimiz olur. Söyle '0.000'.
Biz kullanmak mynumber - 2telafi etmek 0.
3'ün altında numaralar için işe yaramaz It, ancak bazı durumlarda yararlı olabilir.


kullandın track by $index
Ivan Ferrer Villa

bu getto af. her yineleme için bir karakter almak zorunda kalacaksanız da yapabilirsinizng-repeat="i in [1,2,3,4]"
Roi

Tabii ki, OP yinelemenin bir değişkene göre n kez olmasını istiyor$scope.number
Ivan Ferrer Villa

neden 'aaaa' yerine 'abcd' ve sonra parça hurdaya?
omikes

aaaa- çok şık değil - geçici çözümümü açıklamak için bir örnekti. Sabit kodlu 'aaaa' veya 'abcd' kullanarak sabit bir uzunluk listesi elde edersiniz, ancak mynumber-2ondalık sayıları 0'a eklediğinizde , mynumberkarakter içeren bir 'dize' alırsınız . Söyleyin mynumber=5, '0.000'sonra, $ endeksi kullanarak tekrarlıyoruz
Ivan Ferrer Villa


-1

basit yol:

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

bileşen / denetleyici ve ardından:

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

Bu kod benim daktilo projemden ancak saf javascript için yeniden düzenlenebilir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.