Способ NG-повторить определенное количество раз, а не повторять над массивом?

417

Есть ли способ ng-repeat определенному количеству раз вместо того, чтобы всегда перебирать массив?

Например, ниже я хочу, чтобы элемент списка отображался в 5 раз, предполагая, что он $scope.numberравен 5, дополнительно увеличивая число, чтобы каждый элемент списка увеличивался как 1, 2, 3, 4, 5.

Желаемый результат:

<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
источник

Ответы:

569

Обновление (25.09.2008)

Более новые версии AngularJS (> = 1.3.0) позволяют вам делать это только с переменной (функция не требуется):

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

Это было невозможно во время первого вопроса. Благодарим @Nikhil Nambiar от его ответа ниже для этого обновления


Оригинал (29.05.2013)

На данный момент, ng-repeatтолько принимает коллекцию в качестве параметра, но вы можете сделать это:

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

И где-то в вашем контроллере:

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

Это позволит вам изменить $scope.number любой номер на ваше усмотрение и при этом сохранить привязку, которую вы ищете.

РЕДАКТИРОВАТЬ (06.01.2014) - для более новых версий AngularJS (> = 1.1.5) требуется track by $index:

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

Вот скрипка с несколькими списками, использующими одну и ту же getNumberфункцию.

Дэн
источник
Я использую это для нескольких элементов списка, но, кажется, работает только для первого списка. Вы знаете, почему это так?
Malcr001
Это должно работать для любого количества списков. Проверьте эту скрипку
Дан
1
Еще раз спасибо. Я забыл удалить ng-repeat для родительского элемента. Теперь работает. Спасибо.
Malcr001
3
$ scope.getNumber = function (num) {var x = new Array (); for (var i = 0; i <num; i ++) {x.push (i + 1); } return x; } // используем эту функцию, когда число изменяется динамически
Манавендхер
1
@ sh0ber. Когда мне нужно изменить элементы списка на основе значения, выбранного в выпадающем списке. Сначала я попробовал вашу функцию, когда она не работает, я изменил ее на выше, чтобы обновить нет. элементов списка при выборе другого номера в раскрывающемся списке. Можете ли вы проверить мой сценарий, используя вашу функцию.
Манавендхер
135

ты можешь сделать это:

<div ng-repeat="i in [1, 2, 3, 4]">
  ...
</div>
akonsu
источник
1
работал как чудо, протестировано на Chrome v. 39.0.2171.95 (64-разрядная версия), FF v. 33.1.1 и Safari v. 8.0.2
Neara
Это прекрасно работает, если вы используете его в элементе управления нумерацией страниц, где все, что вам нужно, это <li> <a href = "javascript :;" ng-click = "SelectPage ($ index)"> {{i}} </a> </ li>
Рик,
@AdityaMP, используйте это для диапазонов в javascript stackoverflow.com/a/31989462/3160597
azerafati
1
Рассмотрите возможность вызова конструктора массива для массива динамической длины, как указано в этом ответе .
макс. Тысяча
Что делать, если я должен повторить 120 раз. Должен ли я пойти с [1,2,3 ... 120]?
Мункхельгер Туменбаяр
94

Вот пример того, как вы могли бы сделать это. Обратите внимание, что меня вдохновил комментарий в документах ng-repeat: http://jsfiddle.net/digitalzebra/wnWY6/

Обратите внимание на директиву ng-repeat:

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

Вот контроллер:

function TestCtrl($scope) {
    $scope.range = function(n) {
        return new Array(n);
    };
};
Polaris878
источник
8
Вы также можете использовать _.rangeиз Underscore или lodash для создания массива: $ scope.range = _.range (0, n);
дня
83

Я думаю , что это jsFiddle из этой нити может быть то , что вы ищете.

<div ng-app ng-controller="Main">
   <div ng-repeat="item in items | limitTo:2">
       {{item.name}}
   </div>
</div>
jeffmayeur
источник
3
прочитайте далее ссылку на тему Google, и в ней описывается, как вы можете использовать «слайс». например, group1: items.slice (0,3), group2: items.slice (3,6) и т. д.
trevorc 6-13
7
Этот ответ приведет к минимальной нагрузке на ваши контроллеры, и я считаю, что предпочтительным является также угловой подход. Принятый ИМО ответ должен быть заменен следующим.
Мэтт Дженсен
1
Это должен быть принятый ответ (на мой взгляд) - самый элегантный, наиболее нг предпочтительный.
Коди
11
@ Коди К сожалению, нет, это не отвечает на вопрос. OP заявляет «вместо того, чтобы всегда выполнять итерации по массиву» и «предполагая, что $scope.numberравен 5». Намерение состояло в том, чтобы использовать целочисленную переменную для определения количества элементов, а не жестко задавать его и не использовать предопределенный массив.
Дан
5
@Cody @ sh0ber вы можете установить ограничение в своей области ( $scope.limit = 2) и использовать его как ...|limitTo:limit- см. Обновленную скрипку
drzaus
58

Более простой подход будет (для примера 5 раз):

<div ng-repeat="x in [].constructor(5) track by $index">
       ...
</div>
Нихил Намбьяр
источник
5
Brilliant. Читаемые, короткие и не глупые функции в контроллере для возврата нового массива.
макс. Тысяча
2
Я люблю этот путь.
Раввин Шуки Гур
При голосовании это было невозможно, когда вопрос был задан впервые (Angular 1.2). Я изменил принятый ответ, чтобы включить это. Хорошая работа!
Дэн
1
Хотелось бы мне понять, почему этот синтаксис работает, но не работает Array(5)(или даже [...Array(5).keys()]получить массив [0,1,2,3,4])
Дилан Николсон,
50

Я столкнулся с той же проблемой. Я наткнулся на эту тему, но мне не понравились методы, которые они использовали здесь. Мое решение было использовать underscore.js, который мы уже установили. Это так просто, как это:

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

Это сделает именно то, что вы ищете.

Марк Роуч
источник
27
Это хорошо, но обратите внимание, что Underscore по умолчанию не входит в область видимости - вы не сможете использовать его в своем представлении HTML, не сделав что-то подобное $scope._ = _.
jedd.ahyoung
6
Если вы используете lodash или подчеркивание, вы должны вставить его, $rootScopeчтобы его можно было использовать везде. Поместите это в свою app.runфункцию сразу после app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Джереми Мориц
Это был идеальный ответ для меня. Это просто и очень просто. Поскольку я повторял, используя переменную, у которой было число, мне пришлось выполнить ng-repeat = "n в _.range (1, count + 1). Спасибо за решение.
Дэррил
Я попробовал это, и хотя _ отображается в $ rootScope, ng-repeat ничего не рендерит.
Пол
49

Я хотел, чтобы мой HTML был минимальным, поэтому определил небольшой фильтр, который создает массив [0,1,2, ...], как это сделали другие:

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

После этого на виде можно использовать так:

<ul>
  <li ng-repeat="i in 5 | range">
    {{i+1}} <!-- the array will range from 0 to 4 -->
  </li>
</ul>
miguelr
источник
34

Это действительно ужасно, но работает без контроллера для целого числа или переменной:

целое число:

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

переменная:

<span ng-repeat="_ in ((_ = []) && (_.length=myVar) && _) track by $index">{{$index}}</span>
MJ
источник
Лучший взломать когда-либо! Спасибо
Яннис
2
_ in (_ = []).length = 33; _ track by $indexнемного меньше
Fabricio
16

Есть много способов сделать это. Я был действительно обеспокоен наличием логики в моем контроллере, поэтому я создал простую директиву, чтобы решить проблему повторения элемента n раз.

Установка:

Директива может быть установлена ​​с помощью bower install angular-repeat-n

Пример:

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

производит: 1234

Это также работает, используя переменную области видимости:

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

Источник:

Github

connorbode
источник
1
Это то, что они должны рассмотреть, добавив к официальным угловым директивам
HarshaXsoad
13

Это лишь небольшое изменение принятого ответа, но вам не нужно создавать новую функцию. Только для импорта «Массив» в области:

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

Смотрите эту скрипку для живого примера.

Сильвен Леру
источник
4
в курсе (2016) и намного чище!
Жюльен Малидж
9

Самый простой ответ: 2 строки кода

JS (в вашем контроллере 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>

... где repeatCountчисло повторений, которые должны появиться в этом месте.

JellicleCat
источник
1
Я считаю, что это не позволит вам изменить количество повторов в HTML, если оно будет изменено в контроллере, если вы не заключите его в функцию, как это сделали другие ответы.
Trysis,
@trysis: Я не уверен, что понимаю вашу проблему, но вы должны заменить repeatCountфактическое число в HTML, и если это число меньше или равно MAX_REPEATS, это позволит вам установить число повторов в HTML.
JellicleCat
1
На мой взгляд, это самый элегантный способ ограничения ngRepeatдирективы. Использование Array.prototype.sliceи идиоматический JS всегда следует выбирать над библиотекой, например underscore.js (зависит от совместимости браузера).
Пэт Мильяччио,
Неплохое решение, +1, но я думаю, что этот ответ проще и позволяет избежать загромождения контроллера.
максат тысяча
8

angular дает очень приятную функцию, называемую slice . с ее помощью вы можете достичь того, что ищете. например, ng-repeat = "ab in abc.slice (startIndex, endIndex)"

это демо: http://jsfiddle.net/sahilosheal/LurcV/39/ поможет вам и расскажет, как использовать эту функцию «облегчения жизни». :)

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

нг-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
источник
6

Вот ответ на угловой 1.2.x

В основном это то же самое, с небольшой модификацией ng-repeat

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

вот скрипка: http://jsfiddle.net/cHQLH/153/

это связано с тем, что angular 1.2 не допускает дублирования значений в директиве. Это означает, что если вы пытаетесь сделать следующее, вы получите ошибку.

<li ng-repeat="x in [1,1,1]"></li>
DrogoNevets
источник
6

Вы можете использовать ng-if директиву сng-repeat

Итак, если num - это количество повторений элемента:

<li ng-repeat="item in list" ng-if="$index < num">
akaashanky
источник
1
Для тех из вас, кто любит чистую разметку ... Имейте в виду, что использование ng-repeatтаким образом будет выводить его закомментированные теги (и <!-- ngIf: $index < num -->т. Д.). Там просто не будет никаких liэлементов для рендеринга DOM. Проверьте «просмотр источника» на панели результатов здесь, чтобы понять, что я имею в виду.
3

Вы можете использовать этот пример.

Внутри контроллера:

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

Пример для элемента select на стороне 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
источник
3

Для пользователей, использующих CoffeeScript, вы можете использовать диапазон понимания:

директива

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

или контроллер

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

шаблон

<div ng-repeat="i in range">[ the rest of your code ]</div>
Roi
источник
3

Немного расширив первый ответ Ивана, вы можете использовать строку как коллекцию без оператора track by, если символы уникальны, поэтому, если вариант использования меньше 10 чисел, как вопрос, который я бы просто сделал :

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

Это немного странно, конечно, но достаточно просто, чтобы на них взглянуть, и не особенно смущает.

omikes
источник
2

Сначала создайте угловой фильтр, используя LoDash:

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

Функция LoDash times способна обрабатывать нулевые, неопределенные, 0, числа и строковое представление чисел.

Затем используйте его в своем HTML, как это:

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

или

<span ng-repeat="i in myVar | times">
 <!--DO STUFF-->
</span>
Каранвир Канг
источник
1

Мне нужно было более динамичное решение для этого - где я мог бы увеличить повторение.

HTML

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

Дубликатор управления

<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)
}
adswebwork
источник
1

Angular предоставляет фильтры для изменения коллекции. В этом случае коллекция будет нулевой, то есть [], и фильтр также принимает аргументы, как показано ниже:

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

Этот метод очень похож на предложенный выше и не обязательно превосходит его, но показывает мощь фильтров в AngularJS.

Ник Доу
источник
1

Если n не слишком велико, другим вариантом может быть использование split ('') со строкой из n символов:

<div ng-controller="MainCtrl">
<div ng-repeat="a in 'abcdefgh'.split('')">{{$index}}</div>
</div>
vonwolf
источник
я считаю, что раскол здесь не нужен. строка уже является массивом символов.
omikes
1

Я столкнулся с той же проблемой, и вот что я вышел:

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

... и HTML:

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

Живой пример

Я использовал timesфункцию подчеркивания, как мы уже использовали ее в проекте, но вы можете легко заменить ее на собственный код.

nicooga
источник
0

Я создаю директиву многократного использования, где максимальное число будет получено из другого ng-repeat. Итак, это редактирование лучшего ответа.

Просто измените код на контроллере на это -

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

Это вернет новый массив с указанным количеством итераций

sagars01
источник
0

после итерации по строке будет отображаться элемент для каждого символа:

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

мы можем использовать этот уродливый, но без кода обходной путь, используя number|n decimal placesсобственный фильтр.

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

таким образом, у нас будут mynumberэлементы без дополнительного кода. Say '0.000'.
Мы используем mynumber - 2для компенсации. 0.
Это не будет работать для чисел ниже 3, но может быть полезно в некоторых случаях.

Иван Феррер Вилла
источник
ты использовал track by $index?
Иван Феррер Вилла
это гетто аф. если вы будете вынуждены иметь символ для каждой итерации, вы также можете это сделатьng-repeat="i in [1,2,3,4]"
Рой
конечно, но ОП хочет, чтобы итерация была n раз на основе переменной$scope.number
Иван Феррер Вилла
почему бы не «abcd» вместо «aaaa», а затем пересмотреть трек?
omikes
aaaaбыл пример, чтобы объяснить мой - не очень элегантный - обходной путь. Используя жестко закодированные «aaaa» или «abcd», вы получите список фиксированной длины, но добавивmynumber-2 десятичные дробные числа к 0, вы получаете «строку» с mynumberсимволами. Скажем mynumber=5, вы получили '0.000', затем мы повторим это, используя $ index
Иван Феррер Вилла
0
$scope.number = 5;

<div ng-repeat="n in [] | range:$scope.number">
      <span>{{$index}}</span>
</div>
DuFuS
источник
-1

простой способ:

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

в компоненте / контроллере и затем:

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

Этот код взят из моего проекта машинописного текста, но может быть преобразован в чистый JavaScript

Pallepassion
источник