Sayılar ve Aralıklarla Döngü için AngularJS


252

Açısal, HTML yönergelerindeki sayıları kullanarak for for döngüsü için bazı destek sağlar:

<div data-ng-repeat="i in [1,2,3,4,5]">
  do something
</div>

Ancak kapsam değişkeniniz dinamik sayıya sahip bir aralık içeriyorsa, her seferinde boş bir dizi oluşturmanız gerekir.

Denetleyicide

var range = [];
for(var i=0;i<total;i++) {
  range.push(i);
}
$scope.range = range;

HTML'de

<div data-ng-repeat="i in range">
  do something
</div>

Bu çalışır, ancak döngü içinde dizi dizisini kullanmayacağımız için gereksizdir. Min / maks değer için bir aralık veya normal ayarlamayı bilen var mı?

Gibi bir şey:

<div data-ng-repeat="i in 1 .. 100">
  do something
</div>

2
İşte bunun hakkında daha fazla bilgi. yearofmoo.com/2012/10/…
matsko

Yanıtlar:


281

Ben tweaked Bu cevap biraz ve ile geldi bu keman .

Filtre şu şekilde tanımlanır:

var myApp = angular.module('myApp', []);
myApp.filter('range', function() {
  return function(input, total) {
    total = parseInt(total);

    for (var i=0; i<total; i++) {
      input.push(i);
    }

    return input;
  };
});

Bu şekilde kullanılan tekrar ile:

<div ng-repeat="n in [] | range:100">
  do something
</div>

İlginç Chrome kullanırken kemanda bir hata görmüyorum. Hangi tarayıcı?
Gloopy

5
Felaket! ;) Bir filtre bunu yapmanın yolu değildir. İki değerle çalışan yeni bir özellik olmalıdır . Geçerli dizin ve üst sınır.
Ian Warburton

10
@IanWarburton Kriterlerinizi karşılayan bir cevap bulabildiniz mi?
dewd

1
@IanWarburton: Уmed tarafından aşağıda bir direktifle çalışan bir Cevap var, işe yarayamazsınız.
Andresch Serj

1
A ve B arasında bir aralığa ihtiyacım vardı, bu yüzden bu cevabı tweeked jsfiddle.net/h9nLc8mk
Marcio

150

İki tanımlı sayı arasında bir aralık oluşturmak için daha basit bir sürüm buldum, ör. 5 ila 15

Demoyu JSFiddle'da görün

HTML :

<ul>
    <li ng-repeat="n in range(5,15)">Number {{n}}</li>
</ul>

Denetleyici :

$scope.range = function(min, max, step) {
    step = step || 1;
    var input = [];
    for (var i = min; i <= max; i += step) {
        input.push(i);
    }
    return input;
};

14
Bunun gibi şeylere dikkat etmelisiniz. Aralık işlevi, listedeki her öğe için birden çok kez çağrılır. Kötü bellek sızıntıları alabilirsiniz ve birçok işlev çağrısı üretiyorsunuz. Koleksiyonu kontrolörün içine koymak neredeyse daha kolay görünüyor.
Lucas Holt

1
var a; void 0 === a"gerçekten" tanımsız.
andlrc

1
Memoizer deseni ile sonuçları önbelleğe alarak mükemmel vuruşları azaltabilirsiniz. Bellek maliyetinin ne olduğundan emin değilim, ancak bu bir gelişme. tr.wikipedia.org/wiki/Anılaştırma .
Joshua

1
@LucasHolt Sonunda bu örneği güncellemeye başladık. Optimize edilmiş bir sürüm ekledim. Yine de birçok işlev çağrısı olacak, ancak ilk sonucu yeniden kullanacak ve bu da çok daha performans gösterecektir.
sqren

93

Hiçbir şey düz Javascript (bir denetleyiciye bile ihtiyacınız yok):

<div ng-repeat="n in [].constructor(10) track by $index">
    {{ $index }}
</div>

Modelleme yaparken çok kullanışlıdır


Açısal> 1.2.1'de çalışmıyor: Konsolda bu hatayı aldım Referencing "constructor" field in Angular expressions is disallowed! Expression: [].constructor(10). Belki de bu önceki Angular sürümünde çalışıyordu ya da yanlış bir şey yapıyorum.
AWolf

Sanırım bunu 1.3 veya 1.4'te test ettim ve iyiydi. Ayrıştırıcıları geliştirdiklerine inanıyorum, böylece her 'yapıcı' erişimini değil, sadece gerçekten tehlikeli olanları (bu nedenle kod değerlendirmesine [].slice.constructorerişim sağlar Function).
Maël Nison

Tamam teşekkürler. 1.2.1 ile test ettim ve çalışmadı (sürüm jsFiddle açılır listesinde yer alıyor). Ancak 1.3.15 ile çalışıyor. Bu jsFiddle'a bakın .
AWolf

Sayfalandırma için çok yararlı. Teşekkürler;)
Yabancı

69

Bana biraz daha uygun ve isteğe bağlı bir alt sınır ekleyen biraz farklı bir sözdizimi ile geldim:

myApp.filter('makeRange', function() {
        return function(input) {
            var lowBound, highBound;
            switch (input.length) {
            case 1:
                lowBound = 0;
                highBound = parseInt(input[0]) - 1;
                break;
            case 2:
                lowBound = parseInt(input[0]);
                highBound = parseInt(input[1]);
                break;
            default:
                return input;
            }
            var result = [];
            for (var i = lowBound; i <= highBound; i++)
                result.push(i);
            return result;
        };
    });

hangi olarak kullanabilirsiniz

<div ng-repeat="n in [10] | makeRange">Do something 0..9: {{n}}</div>

veya

<div ng-repeat="n in [20, 29] | makeRange">Do something 20..29: {{n}}</div>

Bu harika ama nasıl bütün dolaşırsınız $digest, yani bir kapsamına sahip değerini kullanırken yinelemeleri: ng-repeat="n in [1, maxValue] | makeRange"?
pspahn

Bir ve iki param olgusu highBound'u farklı şekilde tedavi ediyor, tutarlı olmalı
Vajk Hermecz

31

Angularjs için yeni olanlar için. Endeks, $ index kullanılarak elde edilebilir.

Örneğin:

<div ng-repeat="n in [] | range:10">
    do something number {{$index}}
</div>

Hangi Gloopy kullanışlı filtre kullandığınızda, yazdırın: yazdırmak bir
şey yapmak 0 numara bir şey
yapmak 1
numara bir
şey yapmak 2 numara bir
şey yapmak 3 numara bir
şey yapmak 4 numara bir
şey yapmak 5 numara bir
şey yapmak 6 numara bir
şey yapmak 7 numara bir şey yapmak 8
9 numara yapmak


7
Doğru, ama bu durumda do something number {{n}}da yeterli olacaktır.
captncraig

2
Bu kodu Chrome'da çalıştırmaya çalıştığımda konsolda bir hata alıyorum: Hata: [$ injector: unpr] mistakes.angularjs.org/1.2.6/$injector/… ... ... Wa.statements'ta ( ajax.googleapis.com/ajax/libs/angularjs/1.2.6/… ) <! - ngTekrar: [içinde] n | aralık: 10 -> (Ne yazık ki tüm hata izin verilen yorum uzunluğuna sığmayacak kadar uzun, bu yüzden sadece ilk ve son satırı kopyaladım)
Kmeixner

1
Kodunuzla karşılaştırabilmeniz için kodun Plunker örneğini oluşturdum. plnkr.co/edit/tN0156hRfX0M6k9peQ2C?p=preview
Arnoud Sietsema

21

Bunu yapmanın kısa bir yolu Underscore.js'nin _.range () yöntemini kullanmak olacaktır. :)

http://underscorejs.org/#range

// declare in your controller or wrap _.range in a function that returns a dynamic range.
var range = _.range(1, 11);

// val will be each number in the array not the index.
<div ng-repeat='val in range'>
    {{ $index }}: {{ val }}
</div>

1
@jwoodward Bunun bir seçenek olmadığını asla söylemedi. Benim çözümüm, repolarından birim testleri sayesinde bugüne kadarki en basit ve en test edilmiş çözümdür. İstediğiniz zaman js'yi sonlandırılmamış kitaplıktan çıkarabilir ve bir işlev olarak ekleyebilirsiniz.
Michael J.Calkins

4
Doğru, bunu asla söylemedi. Ancak, bir kütüphanedeki bir sorunu başka bir kütüphaneyi uygulayarak çözmek genellikle kötü bir fikirdir, sadece ilk kütüphaneyi nasıl doğru kullanacağınızı öğrenmenizi önler. Mevcut kütüphanede iyi bir çözüm yoksa / başka bir kütüphaneye dönün.
Erik Honn

5
Zaten her yerde lodash kullanıyorum, bu en kolay çözümdü. Teşekkür ederim. Ben sadece $ scope.range = _.range yaptım, o zaman dinamik başlangıç ​​/ bitiş değerleri ile herhangi bir şablonda kullanımı kolaydır.
j_walker_dev

2
@ErikHonn: UnderscoreJS, AngularJS için tamamen farklı bir problem çözer. AngularJS'de aralık oluşturmak için iyi bir çözüm yoktur, çünkü kütüphanenin amacı bu değildir.
AlexFoxGill

2
Bu eski, ama kesinlikle bir aralık oluşturmak gibi şeyler yapmak için tasarlanmış bir kütüphane kullanmak, mevcut kütüphanenizde bir özelliği semantik olmayan bir şekilde kötüye kullanmak yerine gitmek için çok daha iyi bir yol mu? Elbette bir şey öğrenebilirsiniz, ancak başka bir şey için tasarlanmış şeylerin çarpık kullanımları ile sonuçlanırsınız.
Dan

20

Özel ng-repeat-rangeyönergemi kullanıyorum:

/**
 * Ng-Repeat implementation working with number ranges.
 *
 * @author Umed Khudoiberdiev
 */
angular.module('commonsMain').directive('ngRepeatRange', ['$compile', function ($compile) {
    return {
        replace: true,
        scope: { from: '=', to: '=', step: '=' },

        link: function (scope, element, attrs) {

            // returns an array with the range of numbers
            // you can use _.range instead if you use underscore
            function range(from, to, step) {
                var array = [];
                while (from + step <= to)
                    array[array.length] = from += step;

                return array;
            }

            // prepare range options
            var from = scope.from || 0;
            var step = scope.step || 1;
            var to   = scope.to || attrs.ngRepeatRange;

            // get range of numbers, convert to the string and add ng-repeat
            var rangeString = range(from, to + 1, step).join(',');
            angular.element(element).attr('ng-repeat', 'n in [' + rangeString + ']');
            angular.element(element).removeAttr('ng-repeat-range');

            $compile(element)(scope);
        }
    };
}]);

ve html kodu

<div ng-repeat-range from="0" to="20" step="5">
    Hello 4 times!
</div>

ya da sadece

<div ng-repeat-range from="5" to="10">
    Hello 5 times!
</div>

hatta basitçe

<div ng-repeat-range to="3">
    Hello 3 times!
</div>

ya da sadece

<div ng-repeat-range="7">
    Hello 7 times!
</div>

1
Teorik olarak güzel, ama enjeksiyonu element.attr('ng-repeat', 'n in [' + rangeString + ']');işe yaramıyor ...
Stefan Walther

"Kullanırım...". Gerçekten kullanmaya çalıştınız mı? Ng-repeat özelliği derlenmeyecektir.
Peter Hedberg

Teşekkürler Peter, Ive kodu güncelledi. Bu yönergeyi geçmişte kullandım, ama yine de kod
havuzumu

9

En basit kod çözümü aralığı ile bir dizi başlatmak ve $ index + kullanmak ancak ancak ben tarafından dengelemek istiyorum:

<select ng-init="(_Array = []).length = 5;">
    <option ng-repeat="i in _Array track by $index">{{$index+5}}</option>
</select>

7

Yöntem tanımı

Aşağıdaki kod range(), uygulamanızın tüm kapsamı için kullanılabilir bir yöntemi tanımlar MyApp. Davranışı Python range()yöntemine çok benzer .

angular.module('MyApp').run(['$rootScope', function($rootScope) {
    $rootScope.range = function(min, max, step) {
        // parameters validation for method overloading
        if (max == undefined) {
            max = min;
            min = 0;
        }
        step = Math.abs(step) || 1;
        if (min > max) {
            step = -step;
        }
        // building the array
        var output = [];
        for (var value=min; value<max; value+=step) {
            output.push(value);
        }
        // returning the generated array
        return output;
    };
}]);

kullanım

Bir parametre ile:

<span ng-repeat="i in range(3)">{{ i }}, </span>

0, 1, 2,

İki parametre ile:

<span ng-repeat="i in range(1, 5)">{{ i }}, </span>

1, 2, 3, 4,

Üç parametre ile:

<span ng-repeat="i in range(-2, .7, .5)">{{ i }}, </span>

-2, -1.5, -1, -0.5, 0, 0.5,


6

Angular.filter modülünde 'after' veya 'before' filtrelerini kullanabilirsiniz ( https://github.com/a8m/angular-filter )

$scope.list = [1,2,3,4,5,6,7,8,9,10]

HTML:

<li ng-repeat="i in list | after:4">
  {{ i }}
</li>

sonuç: 5, 6, 7, 8, 9, 10


6

Kumandanızda herhangi bir değişiklik yapmadan bunu kullanabilirsiniz:

ng-repeat="_ in ((_ = []) && (_.length=51) && _) track by $index"

Zevk almak!


bir günden fazla mücadele ediyor ve nihayet sadece bu sözdizimi benim için çalıştı
Agnel Amodia

3

En kısa cevap: 2 satır kod

JS (AngularJS kontrol cihazınızda)

$scope.range = new Array(MAX_REPEATS); // MAX_REPEATS should be the most repetitions you will ever need in a single ng-repeat

HTML

<div data-ng-repeat="i in range.slice(0,myCount) track by $index"></div>

... myCountbu yerde görünmesi gereken yıldız sayısı.

$indexHerhangi bir izleme işlemi için kullanabilirsiniz . Örneğin, dizine bir mutasyon yazdırmak istiyorsanız, aşağıdakilere aşağıdakileri koyabilirsiniz div:

{{ ($index + 1) * 0.5 }}

2

UnderscoreJS kullanma:

angular.module('myModule')
    .run(['$rootScope', function($rootScope) { $rootScope.range = _.range; }]);

$rootScopeBunu her yerde kullanılabilir kılmak için uygulamak :

<div ng-repeat="x in range(1,10)">
    {{x}}
</div>

2

Çok basit olanı:

$scope.totalPages = new Array(10);

 <div id="pagination">
    <a ng-repeat="i in totalPages track by $index">
      {{$index+1}}
    </a>   
 </div> 

2

Merhaba bunu AngularJS kullanarak saf html kullanarak elde edebilirsiniz (NO Direktifi gereklidir!)

<div ng-app="myapp" ng-controller="YourCtrl" ng-init="x=[5];">
  <div ng-if="i>0" ng-repeat="i in x">
    <!-- this content will repeat for 5 times. -->
    <table class="table table-striped">
      <tr ng-repeat="person in people">
         <td>{{ person.first + ' ' + person.last }}</td>
      </tr>
    </table>
    <p ng-init="x.push(i-1)"></p>
  </div>
</div>

1

Denetleyicide Kapsam Belirle

var range = [];
for(var i=20;i<=70;i++) {
  range.push(i);
}
$scope.driverAges = range;

Html Şablon Dosyasında Tekrar Ayarla

<select type="text" class="form-control" name="driver_age" id="driver_age">
     <option ng-repeat="age in driverAges" value="{{age}}">{{age}}</option>
</select>

1

@ Mormegil'in çözümünde iyileştirme

app.filter('makeRange', function() {
  return function(inp) {
    var range = [+inp[1] && +inp[0] || 0, +inp[1] || +inp[0]];
    var min = Math.min(range[0], range[1]);
    var max = Math.max(range[0], range[1]);
    var result = [];
    for (var i = min; i <= max; i++) result.push(i);
    if (range[0] > range[1]) result.reverse();
    return result;
  };
});

kullanım

<span ng-repeat="n in [3, -3] | makeRange" ng-bind="n"></span>

3 2 1 0 -1 -2 -3

<span ng-repeat="n in [-3, 3] | makeRange" ng-bind="n"></span>

-3 -2 -1 0 1 2 3

<span ng-repeat="n in [3] | makeRange" ng-bind="n"></span>

0 1 2 3

<span ng-repeat="n in [-3] | makeRange" ng-bind="n"></span>

0 -1 -2 -3


1

Aşağıdaki denedim ve benim için iyi çalıştı:

<md-radio-button ng-repeat="position in formInput.arrayOfChoices.slice(0,6)" value="{{position}}">{{position}}</md-radio-button>

Açısal 1.3.6


1

Partiye geç. Ama ben sadece bunu yaparak sona erdi:

Kumandanızda:

$scope.repeater = function (range) {
    var arr = []; 
    for (var i = 0; i < range; i++) {
        arr.push(i);
    }
    return arr;
}

Html:

<select ng-model="myRange">
    <option>3</option>
    <option>5</option>
</select>

<div ng-repeat="i in repeater(myRange)"></div>

1

Bu jzm gelişmiş cevap (s / o hataları dahil çünkü ben onun / onun yorum yorum yapamam başka yorum yapamam). İşlev bir başlangıç ​​/ bitiş aralığı değerine sahiptir, bu nedenle daha esnektir ve ... çalışır. Bu özel durum ayın günüdür:

$scope.rangeCreator = function (minVal, maxVal) {
    var arr = [];
   for (var i = minVal; i <= maxVal; i++) {
      arr.push(i);
   }
   return arr;
};


<div class="col-sm-1">
    <select ng-model="monthDays">
        <option ng-repeat="day in rangeCreator(1,31)">{{day}}</option>
    </select>
</div>

0

Bunu çırptım ve bazıları için yararlı olabileceğini gördüm. (Evet, CoffeeScript. Beni dava et.)

Direktif

app.directive 'times', ->
  link: (scope, element, attrs) ->
    repeater = element.html()
    scope.$watch attrs.times, (value) ->
      element.html ''
      return unless value?
      element.html Array(value + 1).join(repeater)

Kullanmak:

HTML

<div times="customer.conversations_count">
  <i class="icon-picture></i>
</div>

Bu daha basit olabilir mi?

Filtreler konusunda ihtiyatlıyım çünkü Angular her zaman iyi bir sebep olmaksızın bunları yeniden değerlendirmeyi seviyor ve benim gibi binlerce tane varsa, büyük bir darboğaz var.

Bu yönerge, modelinizdeki değişiklikleri bile izleyecek ve öğeyi buna göre güncelleyecektir.


Bu güzel, ama ngRepeat kendi kapsamını korur. Bu nedenle, eklenen her öğe için derleme çalıştırmanız gerekir. NgRepeat bunu sizin için yaptığı için animasyonları da taklit etmeniz gerekir.
matsko

2
Katkıda bulunduğunuz için teşekkür ederiz, ancak OP'nin kahve metnini bildiğini varsayarak, ne olduğunu, JS'ye nasıl derleyeceğinizi veya bunun gibi herhangi bir oluşturma aracını kullandığı çok büyük bir esnektir. Hepimiz öğrenmek ya da yardım etmek için buradayız, bu yüzden, ekstra mil gidin, o köpek yavrusu dönüştürün. (
Augie Gardner

0
<div ng-init="avatars = [{id : 0}]; flag = true ">
  <div ng-repeat='data in avatars' ng-if="avatars.length < 10 || flag"
       ng-init="avatars.length != 10 ? avatars.push({id : $index+1}) : ''; flag = avatars.length <= 10 ? true : false">
    <img ng-src="http://actual-names.com/wp-content/uploads/2016/01/sanskrit-baby-girl-names-400x275.jpg">
  </div>
</div>

Bunu herhangi bir kontrolör veya fabrika olmadan html'de elde etmek istiyorsanız.


0

Diyelim ki $scope.refernceurlbir dizi

for(var i=0; i<$scope.refernceurl.length; i++){
    $scope.urls+=$scope.refernceurl[i].link+",";
}

-8

Bu en basit varyant: sadece tamsayılar dizisini kullanın ....

 <li ng-repeat="n in [1,2,3,4,5]">test {{n}}</li>


3
Bu korkunç.
Tiffany Lowe

@Stefan, büyük olasılıkla downvotes alıyorsunuz çünkü çözüm sabit kodlu koleksiyonları kullanamıyor.
Tass
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.