AngularJS Untuk Loop dengan Angka & Kisaran

252

Angular memang menyediakan beberapa dukungan untuk loop menggunakan angka-angka dalam arahan HTML-nya:

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

Tetapi jika variabel lingkup Anda mencakup rentang yang memiliki angka dinamis maka Anda harus membuat array kosong setiap kali.

Di controller

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

Dalam HTML

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

Ini berfungsi, tetapi itu tidak perlu karena kita tidak akan menggunakan array jangkauan sama sekali dalam loop. Apakah ada yang tahu pengaturan rentang atau reguler untuk nilai min / maks?

Sesuatu seperti:

<div data-ng-repeat="i in 1 .. 100">
  do something
</div>
matsko
sumber
2
Berikut ini beberapa info lebih lanjut tentang ini. yearofmoo.com/2012/10/…
matsko

Jawaban:

281

Saya tweak jawaban ini sedikit dan muncul dengan biola ini .

Filter didefinisikan sebagai:

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

Dengan pengulangan yang digunakan seperti ini:

<div ng-repeat="n in [] | range:100">
  do something
</div>
Gloopy
sumber
Menarik Saya tidak melihat kesalahan dalam biola menggunakan Chrome. Browser yang mana?
Gloopy
5
Mengerikan! ;) Filter bukan cara untuk melakukan ini. Itu harus atribut baru yang berfungsi dengan dua nilai. Indeks saat ini dan batas atas.
Ian Warburton
10
@IanWarburton Apakah Anda dapat menemukan jawaban yang memenuhi kriteria Anda?
dewd
1
@IanWarburton: Ada Jawaban oleh Уmed di bawah ini yang berfungsi dengan arahan, Anda tidak bisa menjalankannya.
Andresch Serj
1
Saya membutuhkan rentang antara A dan B jadi saya tweek jawaban ini jsfiddle.net/h9nLc8mk
Marcio
150

Saya datang dengan versi yang lebih sederhana, untuk membuat rentang antara dua angka yang ditentukan, misalnya. 5 hingga 15

Lihat demo di JSFiddle

HTML :

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

Pengendali :

$scope.range = function(min, max, step) {
    step = step || 1;
    var input = [];
    for (var i = min; i <= max; i += step) {
        input.push(i);
    }
    return input;
};
sqren
sumber
14
Anda harus berhati-hati terhadap hal-hal seperti ini. Fungsi rentang akan dipanggil beberapa kali untuk setiap item dalam daftar. Anda bisa mendapatkan kebocoran memori yang tidak menyenangkan dan Anda menghasilkan banyak panggilan fungsi. Tampaknya lebih mudah untuk meletakkan koleksi di dalam pengontrol.
Lucas Holt
1
var a; void 0 === a"sungguh" tidak terdefinisi.
andlrc
1
Anda dapat mengurangi perf hit dengan menyimpan hasil melalui pola memoizer. Tidak yakin berapa biaya ingatannya, tetapi ini merupakan peningkatan. en.wikipedia.org/wiki/Memoization .
Joshua
1
@LucasHolt Akhirnya sempat memperbarui contoh ini. Saya telah menambahkan versi yang dioptimalkan. Masih akan ada banyak panggilan fungsi, tetapi akan menggunakan kembali hasil pertama yang membuatnya jauh lebih hebat.
sqren
93

Hanya Javascript biasa (Anda bahkan tidak perlu controller):

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

Sangat berguna saat mockuping

Maël Nison
sumber
Tidak berfungsi di Angular> 1.2.1: Saya mendapatkan kesalahan ini di konsol Referencing "constructor" field in Angular expressions is disallowed! Expression: [].constructor(10). Mungkin itu bekerja di versi Angular sebelumnya atau saya melakukan sesuatu yang salah.
AWolf
Saya rasa saya menguji ini pada 1,3 atau 1,4 dan itu baik-baik saja. Saya percaya mereka telah meningkatkan parser sehingga tidak menolak setiap akses 'konstruktor' tetapi hanya yang benar-benar berbahaya (seperti [].slice.constructor, yang memberikan akses Function, maka untuk evaluasi kode).
Maël Nison
Ok terima kasih. Saya mengujinya dengan 1.2.1 dan tidak berfungsi (versi disertakan dalam jsFiddle dropdown). Tetapi dengan 1.3.15 itu berfungsi. Lihat jsFiddle ini .
AWolf
Sangat berguna untuk pagination. Terima kasih;)
Orang Asing
69

Saya datang dengan sintaks yang sedikit berbeda yang cocok untuk saya sedikit lebih dan menambahkan batas bawah opsional juga:

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

yang dapat Anda gunakan sebagai

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

atau

<div ng-repeat="n in [20, 29] | makeRange">Do something 20..29: {{n}}</div>
Mormegil
sumber
Ini bagus, tapi bagaimana Anda mendapatkan sekitar semua $digestiterasi ketika menggunakan nilai scoped, yaitu: ng-repeat="n in [1, maxValue] | makeRange"?
pspahn
Satu dan dua kasus param memperlakukan highBound secara berbeda, harus konsisten
Vajk Hermecz
31

Bagi mereka yang baru menggunakan angular. Indeks bisa didapat dengan menggunakan $ index.

Sebagai contoh:

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

Yang mana, ketika Anda menggunakan filter praktis Gloopy, cetak:
lakukan sesuatu nomor 0
lakukan sesuatu nomor 1
lakukan sesuatu nomor 2
lakukan sesuatu nomor 3
lakukan sesuatu nomor 5
lakukan sesuatu nomor 5
lakukan sesuatu nomor 6
lakukan sesuatu nomor 7
lakukan sesuatu nomor 8
lakukan sesuatu nomor 9

Arnoud Sietsema
sumber
7
Benar, tetapi dalam hal ini do something number {{n}}juga sudah cukup.
captncraig
2
Ketika saya mencoba menjalankan kode ini di Chrome, saya mendapatkan kesalahan di konsol: Kesalahan: [$ injector: uns] errors.angularjs.org/1.2.6/$injector/ ... ... ... di Wa.statements ( ajax.googleapis.com/ajax/libs/angularjs/1.2.6/… ) <! - ngRepeat: n di [] | range: 10 -> (Sayangnya seluruh kesalahan terlalu panjang untuk dimasukkan dalam panjang komentar yang diizinkan jadi saya hanya menyalin baris pertama dan terakhir)
Kmeixner
1
Saya telah membuat contoh kode Plunker sehingga Anda dapat membandingkannya dengan kode Anda. plnkr.co/edit/tN0156hRfX0M6k9peQ2C?p=preview
Arnoud Sietsema
21

Cara singkat untuk melakukan ini adalah dengan menggunakan metode _.range () Underscore.js. :)

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>
Michael J. Calkins
sumber
1
@woodward Dia tidak pernah mengatakan itu bukan pilihan. Solusi saya sejauh ini adalah yang paling sederhana dan teruji berkat pengujian unit dari repo mereka. Anda selalu dapat mengambil js dari perpustakaan yang tidak dijinakkan dan memasukkannya sebagai fungsi.
Michael J. Calkins
4
Benar, dia tidak pernah mengatakan itu. Tapi itu umumnya ide yang buruk untuk memecahkan masalah di satu perpustakaan dengan menerapkan perpustakaan lain, itu hanya mencegah Anda belajar bagaimana menggunakan perpustakaan pertama dengan benar. Beralih ke perpustakaan lain ketika / jika tidak ada solusi yang baik di perpustakaan saat ini.
Erik Honn
5
Saya sudah menggunakan lodash di mana-mana, sejauh ini solusi yang paling mudah. Terima kasih. Saya baru saja melakukan $ scope.range = _.range, lalu mudah digunakan dalam template apa pun dengan nilai awal / akhir dinamis.
j_walker_dev
2
@ErikHonn: UnderscoreJS memecahkan masalah yang sama sekali berbeda dengan AngularJS. Tidak ada solusi yang baik untuk menghasilkan rentang di AngularJS karena itu bukan tujuan perpustakaan.
AlexFoxGill
2
Ini sudah tua, tetapi pasti menggunakan perpustakaan yang dirancang untuk melakukan hal-hal persis seperti membuat rentang, alih-alih menyalahgunakan fitur di perpustakaan Anda saat ini dengan cara non-semantik adalah cara yang jauh lebih baik untuk pergi? Tentu Anda dapat mempelajari sesuatu, tetapi Anda berakhir dengan penggunaan yang salah dari hal-hal yang dirancang untuk hal lain.
Dan
20

Saya menggunakan ng-repeat-rangearahan khusus saya :

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

dan kode html adalah

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

atau sederhana

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

atau bahkan sederhana

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

atau hanya

<div ng-repeat-range="7">
    Hello 7 times!
</div>
pleerock
sumber
1
Secara teoritis bagus, tetapi suntikan element.attr('ng-repeat', 'n in [' + rangeString + ']');tidak berfungsi ...
Stefan Walther
"Saya menggunakan...". Sudahkah Anda benar-benar mencoba menggunakannya? Atribut ng-repeat tidak akan dikompilasi.
Peter Hedberg
Terima kasih Peter, saya telah memperbarui kodenya. Saya menggunakan arahan ini di masa lalu, tetapi masih meninggalkan repositori kode saya
pleerock
9

Solusi tanpa kode paling sederhana adalah init array dengan range, dan gunakan $ index + betapapun saya ingin mengimbangi dengan:

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

Definisi metode

Kode di bawah ini mendefinisikan metode yang range()tersedia untuk seluruh ruang lingkup aplikasi Anda MyApp. Perilakunya sangat mirip dengan range()metode Python .

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

Pemakaian

Dengan satu parameter:

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

0, 1, 2,

Dengan dua parameter:

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

1, 2, 3, 4,

Dengan tiga parameter:

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

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

Mathieu Rodic
sumber
6

Anda dapat menggunakan filter 'setelah' atau 'sebelum' dalam modul angular.filter ( 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>

hasil: 5, 6, 7, 8, 9, 10

a8m
sumber
6

Tanpa perubahan pada pengontrol Anda, Anda dapat menggunakan ini:

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

Nikmati!

odroz
sumber
telah berjuang lebih dari sehari dan akhirnya hanya sintaks ini yang bekerja untuk saya
Agnel Amodia
3

Jawaban terpendek: 2 baris kode

JS (di pengontrol AngularJS Anda)

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

... di mana myCountjumlah bintang yang seharusnya muncul di lokasi ini.

Kamu bisa memakai $index untuk operasi pelacakan apa pun. Misalnya jika Anda ingin mencetak beberapa mutasi pada indeks, Anda dapat memasukkan yang berikut ini di div:

{{ ($index + 1) * 0.5 }}
JellicleCat
sumber
2

Menggunakan UnderscoreJS:

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

Menerapkan ini untuk $rootScopemembuatnya tersedia di mana-mana:

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

Sangat sederhana:

$scope.totalPages = new Array(10);

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

Hai, Anda dapat mencapainya menggunakan html murni menggunakan AngularJS (TIDAK diperlukan Instruksi!)

<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>
Pavan Kosanam
sumber
1

Atur Lingkup di pengontrol

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

Atur Ulangi di File Template Html

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

Perbaikan untuk solusi @ Mormegil

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

pemakaian

<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

thaliberalsurfer
sumber
1

Saya mencoba yang berikut ini dan berhasil baik untuk saya:

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

Sudut 1.3.6

araghorn
sumber
1

Terlambat ke pesta. Tetapi akhirnya saya hanya melakukan ini:

Di controller Anda:

$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>
mnsr
sumber
1

Ini adalah jawaban yang ditingkatkan jzm (saya tidak bisa berkomentar lain saya akan mengomentari jawabannya karena ia termasuk kesalahan). Fungsi ini memiliki nilai rentang awal / akhir, jadi lebih fleksibel, dan ... berfungsi. Kasus khusus ini untuk hari bulan:

$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>
fresko
sumber
0

Saya menyiapkan ini dan melihatnya mungkin bermanfaat bagi sebagian orang. (Ya, CoffeeScript. Sue me.)

Pengarahan

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)

Menggunakan:

HTML

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

Bisakah ini menjadi lebih sederhana?

Saya khawatir tentang filter karena Angular suka mengevaluasi ulang tanpa alasan yang baik sepanjang waktu, dan ini merupakan hambatan besar jika Anda memiliki ribuan filter seperti yang saya lakukan.

Arahan ini bahkan akan mengawasi perubahan dalam model Anda, dan memperbarui elemen yang sesuai.

Prathan Thananart
sumber
Ini bagus, tetapi ngRepeat mempertahankan pelingkupan itu sendiri. Jadi, Anda harus menjalankan kompilasi untuk setiap item yang ditambahkan. Anda juga harus meniru animasi karena ngRepeat melakukan itu untuk Anda.
matsko
2
Terima kasih telah berkontribusi, tetapi dengan asumsi OP tahu coffeescript, apa itu, bagaimana mengkompilasinya kembali ke JS, atau pernah menggunakan alat membangun seperti itu sangat melelahkan. Kita semua di sini untuk belajar atau membantu, jadi, lakukan yang terbaik, ubah anak anjing itu. (Anda telah dituntut!)
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>

Jika Anda ingin mencapai ini dalam html tanpa pengontrol atau pabrik.

Virendra Singh Rathore
sumber
0

Misalkan $scope.refernceurlarray

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

Ini adalah varian paling sederhana: cukup gunakan array bilangan bulat ....

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

Stefan
sumber
3
Ini mengerikan.
Tiffany Lowe
@Stefan, Anda kemungkinan menerima downvotes karena solusi tidak dapat menggunakan koleksi hard-coded.
Tass