AngularJS cho vòng lặp với số & phạm vi


252

Angular cung cấp một số hỗ trợ cho vòng lặp for bằng cách sử dụng các số trong các chỉ thị HTML của nó:

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

Nhưng nếu biến phạm vi của bạn bao gồm một phạm vi có số động thì bạn sẽ cần tạo một mảng trống mỗi lần.

Trong bộ điều khiển

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

Trong HTML

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

Điều này hoạt động, nhưng không cần thiết vì chúng ta sẽ không sử dụng mảng phạm vi trong vòng lặp. Có ai biết thiết lập một phạm vi hoặc thường xuyên cho giá trị tối thiểu / tối đa không?

Cái gì đó như:

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

2
Dưới đây là một số thông tin thêm về điều này. yearofmoo.com/2012/10/ từ
matko

Câu trả lời:


281

Tôi đã điều chỉnh câu trả lời này một chút và đưa ra câu đố này .

Bộ lọc được xác định là:

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

Với việc lặp lại được sử dụng như thế này:

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

Thú vị là tôi không thấy lỗi trong fiddle khi sử dụng Chrome. Trình duyệt nào?
Toàn cảnh

5
Kinh khủng! ;) Một bộ lọc không phải là cách để làm điều này. Nó phải là một thuộc tính mới hoạt động với hai giá trị. Các chỉ số hiện tại và giới hạn trên.
Ian Warburton

10
@IanWarburton Bạn có thể đưa ra câu trả lời đáp ứng tiêu chí của bạn không?
sương

1
@IanWarburton: Có một câu trả lời bằng cách dưới đây hoạt động với một chỉ thị, bạn không thể làm cho nó hoạt động.
Andresch Serj

1
Tôi cần một phạm vi giữa A và B vì vậy tôi đã tìm ra câu trả lời này jsfiddle.net/h9nLc8mk
Marcio

150

Tôi đã đưa ra một phiên bản thậm chí đơn giản hơn, để tạo ra một phạm vi giữa hai số được xác định, ví dụ. 5 đến 15

Xem bản demo trên JSFiddle

HTML :

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

Điều khiển :

$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
Bạn phải coi chừng những thứ như thế này. Hàm phạm vi sẽ được gọi nhiều lần cho mỗi mục trong danh sách. Bạn có thể bị rò rỉ bộ nhớ khó chịu và bạn đang tạo ra rất nhiều cuộc gọi chức năng. Có vẻ như dễ dàng hơn để đặt bộ sưu tập bên trong bộ điều khiển.
Lucas Holt

1
var a; void 0 === a"thực sự" không xác định.
andlrc

1
Bạn có thể giảm cú đánh hoàn hảo bằng cách lưu trữ kết quả qua mẫu ghi nhớ. Không chắc chắn chi phí bộ nhớ là gì, nhưng nó là một cải tiến. vi.wikipedia.org/wiki/Memoization .
Joshua

1
@LucasHolt Cuối cùng cũng có cách cập nhật ví dụ này. Tôi đã thêm một phiên bản tối ưu hóa. Nó vẫn sẽ có nhiều lệnh gọi hàm, nhưng nó sẽ sử dụng lại kết quả đầu tiên giúp nó hoạt động hiệu quả hơn nhiều.
sqren

93

Không có gì ngoài Javascript đơn giản (bạn thậm chí không cần bộ điều khiển):

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

Rất hữu ích khi chế nhạo


Không hoạt động trong Angular> 1.2.1: Tôi đã gặp lỗi này trong bảng điều khiển Referencing "constructor" field in Angular expressions is disallowed! Expression: [].constructor(10). Có lẽ điều đó đã hoạt động trong phiên bản trước của Angular hoặc tôi đang làm gì đó sai.
AWolf

Tôi nghĩ rằng tôi đã thử nghiệm điều này trên 1.3 hoặc 1.4 và nó vẫn ổn. Tôi tin rằng họ đã cải thiện trình phân tích cú pháp để nó không từ chối mọi quyền truy cập của 'nhà xây dựng' mà chỉ những người thực sự nguy hiểm (chẳng hạn như [].slice.constructor, cho phép truy cập Function, do đó để đánh giá mã).
Maël Nison

Được rồi cảm ơn. Tôi đã thử nghiệm nó với 1.2.1 và nó không hoạt động (phiên bản có trong danh sách thả xuống jsFiddle). Nhưng với 1.3.15 nó đang hoạt động. Xem jsFiddle này .
AWolf

Rất hữu ích cho phân trang. Cảm ơn;)
Người lạ

69

Tôi đã đưa ra một cú pháp hơi khác, phù hợp với tôi hơn một chút và cũng thêm một ràng buộc thấp hơn tùy chọn:

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

mà bạn có thể sử dụng như

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

hoặc là

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

Điều này thật tuyệt, nhưng làm thế nào để bạn có được xung quanh tất cả các $digestlần lặp khi sử dụng giá trị phạm vi, nghĩa là : ng-repeat="n in [1, maxValue] | makeRange"?
pspahn

Một và hai trường hợp param đối xử với highBound khác nhau, nó phải nhất quán
Vajk Hermecz

31

Đối với những người mới đến angularjs. Chỉ mục có thể nhận được bằng cách sử dụng $ index.

Ví dụ:

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

Khi bạn đang sử dụng bộ lọc tiện dụng của Gloopy, hãy in:
làm gì đó số 0
làm điều gì đó số 1
làm điều gì đó số 2
làm điều gì đó số 3
làm điều gì đó số 4
làm điều gì đó số 5
làm điều gì đó số 6
làm điều gì đó số 7
làm điều gì đó số 8
làm gì đó số 9


7
Đúng, nhưng trong trường hợp do something number {{n}}này cũng sẽ đủ.
captncraig

2
Khi tôi cố chạy mã này trong Chrome, tôi gặp lỗi trong bảng điều khiển: Lỗi: [$ kim phun: uns ] lỗi.angularjs.org / 1.2.6 /$injection / sắt ... ... tại Wa.statements ( ajax.googleapis.com/ajax/libs/angularjs/1.2.6/ trên ) <! - ngRepeat: n in [] | phạm vi: 10 -> (Thật không may, toàn bộ lỗi quá dài để phù hợp với độ dài bình luận được phép nên tôi chỉ sao chép dòng đầu tiên và dòng cuối cùng)
Kmeixner

1
Tôi đã tạo một ví dụ Plunker về mã để bạn có thể so sánh nó với mã của mình. plnkr.co/edit/tN0156hRfX0M6k9peQ2C?p=preview
Arnoud Sietsema

21

Một cách ngắn để làm điều này sẽ là sử dụng phương thức _.range () của 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>

1
@jwoodward Anh ấy không bao giờ nói rằng đó không phải là một lựa chọn. Giải pháp của tôi cho đến nay là đơn giản nhất và được thử nghiệm nhiều nhất nhờ thử nghiệm đơn vị từ repo của họ. Bạn luôn có thể đưa js ra khỏi thư viện chưa hoàn thành và đưa nó vào dưới dạng hàm.
Michael J. Calkins

4
Đúng vậy, anh không bao giờ nói thế. Nhưng nói chung là một ý tưởng tồi để giải quyết vấn đề trong một thư viện bằng cách áp dụng một thư viện khác, nó chỉ ngăn bạn học cách sử dụng thư viện đầu tiên đúng cách. Chuyển sang thư viện khác khi / nếu không có giải pháp tốt trong thư viện hiện tại.
Erik Honn

5
Tôi đã sử dụng lodash ở khắp mọi nơi, đây là giải pháp đơn giản nhất. Cảm ơn bạn. Tôi mới thực hiện $ scope.range = _.range, sau đó dễ sử dụng trong bất kỳ mẫu nào có giá trị bắt đầu / kết thúc động.
j_walker_dev

2
@ErikHonn: UnderscoreJS giải quyết một vấn đề hoàn toàn khác với AngularJS. Không có giải pháp tốt để tạo phạm vi trong AngularJS vì đó không phải là mục đích của thư viện.
AlexFoxGill

2
Điều này đã cũ, nhưng chắc chắn sử dụng một thư viện được thiết kế để thực hiện chính xác như tạo một phạm vi, thay vì lạm dụng một tính năng trong thư viện hiện tại của bạn theo cách phi ngữ nghĩa là cách tốt hơn nhiều? Chắc chắn bạn có thể học được điều gì đó, nhưng cuối cùng bạn lại bị sử dụng méo mó những thứ được thiết kế cho thứ khác.
Dan

20

Tôi sử dụng ng-repeat-rangechỉ thị tùy chỉnh của mình :

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

và mã html là

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

hoặc đơn giản

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

hoặc thậm chí đơn giản

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

hoặc chỉ

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

1
Về mặt lý thuyết tốt đẹp, nhưng việc tiêm thuốc element.attr('ng-repeat', 'n in [' + rangeString + ']');không hiệu quả ...
Stefan Walther

"Tôi sử dụng...". Bạn đã thực sự cố gắng sử dụng nó? Thuộc tính ng-repeat sẽ không được biên dịch.
Peter Hedberg

Cảm ơn Peter, Ive đã cập nhật mã. Tôi đã sử dụng lệnh này trong quá khứ, nhưng nó vẫn để lại kho lưu trữ mã của tôi
pleerock

9

Đơn giản nhất, không có giải pháp mã nào là khởi tạo một mảng với phạm vi và sử dụng chỉ mục $ + tuy nhiên tôi muốn bù lại bằng:

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

7

Định nghĩa phương thức

Mã dưới đây xác định một phương thức range()có sẵn cho toàn bộ phạm vi ứng dụng của bạn MyApp. Hành vi của nó rất giống với range()phương thức 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;
    };
}]);

Sử dụng

Với một tham số:

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

0, 1, 2,

Với hai tham số:

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

1, 2, 3, 4,

Với ba tham số:

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

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


6

Bạn có thể sử dụng các bộ lọc 'sau' hoặc 'trước' trong mô-đun 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>

kết quả: 5, 6, 7, 8, 9, 10


6

Nếu không có bất kỳ thay đổi nào trong bộ điều khiển của bạn, bạn có thể sử dụng điều này:

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

Thưởng thức!


đã phải vật lộn hơn một ngày và cuối cùng chỉ có cú pháp này hiệu quả với tôi
Agnel Amodia

3

Câu trả lời ngắn nhất: 2 dòng mã

JS (trong bộ điều khiển AngularJS của bạn)

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

... myCountSố lượng ngôi sao sẽ xuất hiện ở vị trí này.

Bạn có thể sử dụng $indexcho bất kỳ hoạt động theo dõi. Ví dụ: nếu bạn muốn in một số đột biến trên chỉ mục, bạn có thể đặt các mục sau vào div:

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

2

Sử dụng UnderscoreJS:

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

Áp dụng điều này để $rootScopelàm cho nó có sẵn ở khắp mọi nơi:

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

2

Rất đơn giản:

$scope.totalPages = new Array(10);

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

2

Xin chào, bạn có thể đạt được điều này bằng cách sử dụng html thuần bằng cách sử dụng AngularJS (KHÔNG yêu cầu Chỉ thị!)

<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

Đặt Phạm vi trong bộ điều khiển

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

Đặt Lặp lại trong Tệp Mẫu Html

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

1

Một cải tiến cho giải pháp của @ 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;
  };
});

sử dụng

<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

Tôi đã thử những điều sau đây và nó hoạt động tốt với tôi:

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

Góc 1.3.6


1

Đi dự tiệc muộn. Nhưng cuối cùng tôi chỉ làm điều này:

Trong bộ điều khiển của bạn:

$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

Đây là câu trả lời được cải thiện của jzm (tôi không thể bình luận gì khác, tôi sẽ bình luận câu trả lời của cô ấy / anh ấy vì anh ấy đã bao gồm lỗi). Hàm này có giá trị phạm vi bắt đầu / kết thúc, do đó, nó linh hoạt hơn và ... nó hoạt động. Trường hợp cụ thể này là cho ngày trong tháng:

$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

Tôi đã đánh nó lên và thấy nó có thể hữu ích cho một số người. (Vâng, CoffeeScript. Kiện tôi.)

Chỉ thị

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)

Để sử dụng:

HTML

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

Điều này có thể nhận được bất kỳ đơn giản hơn?

Tôi cảnh giác với các bộ lọc vì Angular thích đánh giá lại chúng mà không có lý do chính đáng mọi lúc, và đó là một nút cổ chai lớn nếu bạn có hàng ngàn trong số chúng như tôi.

Lệnh này thậm chí sẽ theo dõi các thay đổi trong mô hình của bạn và cập nhật phần tử tương ứng.


Điều này là tốt, nhưng ngRepeat duy trì phạm vi riêng của nó. Vì vậy, bạn sẽ phải chạy biên dịch cho từng mục được thêm vào. Bạn cũng cần phải mô phỏng hoạt hình vì ngRepeat làm điều đó cho bạn.
Matsko

2
Cảm ơn bạn đã đóng góp, nhưng giả sử OP biết coffeescript, nó là gì, làm thế nào để biên dịch lại cho JS hoặc đã từng sử dụng bất kỳ công cụ xây dựng nào như thế là rất lớn. Tất cả chúng ta đều ở đây để học hỏi hoặc giúp đỡ, vì vậy, hãy đi xa hơn, chuyển đổi chú chó con đó. (Bạn đã bị kiệ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>

Nếu bạn muốn đạt được điều này trong html mà không cần bất kỳ bộ điều khiển hoặc nhà máy nào.


0

Giả sử $scope.refernceurllà một mảng rồi

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

-8

Đây là biến thể đơn giản nhất: chỉ cần sử dụng mảng số nguyên ....

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


3
Điều này thật kinh khủng.
Tiffany Lowe

@Stefan, bạn có thể nhận được downvote vì giải pháp không thể sử dụng các bộ sưu tập được mã hóa cứng.
Tass
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.