Спосіб 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>


Відповіді:


569

Оновлення (25.09.2018)

Новіші версії 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будь-яку кількість за вашим бажанням і все одно підтримувати прив’язку, яку ви шукаєте.

EDIT (1/6/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-повтор з батьківського елемента. Зараз це працює. Дякую.
Malcr001

3
$ range.getNumber = функція (число) {var x = новий масив (); для (var i = 0; i <num; i ++) {x.push (i + 1); } повернути х; } // використовувати цю функцію, коли число змінюється динамічно
Manavendher

1
@ sh0ber. Коли мені потрібно змінити елементи списку на основі значення, вибраного в спадному номері. Спершу я спробував вашу функцію, коли вона не працює, я змінив її на вище, щоб оновити номер no. елементів списку, коли в спадному меню вибирається інша кількість Чи можете ви, будь ласка, перевірити мій сценарій за допомогою своєї функції.
Manavendher

135

Ви можете це зробити:

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

1
працював як шарм, протестований на Chrome v. 39.0.2171.95 (64-розрядні), FF проти 33.1.1 та Safari проти 8.0.2
Neara

Це чудово працює, якщо ви використовуєте його в контролі сторінки, де все, що вам потрібно, - <li> <a href = "javascript:;" ng-click = "SelectPage ($ index)"> {{i}} </a> </li>
Rick

@AdityaMP, використовувати це для діапазонів в JavaScript stackoverflow.com/a/31989462/3160597
azerafati

1
Розглянемо виклик конструктора масиву для масиву динамічної довжини, як зазначено в цій відповіді .
maxathousand

що робити, якщо мені доведеться повторити 120 разів. Чи варто йти з [1,2,3 ... 120]?
Munkhdelger Tumenbayar

94

Ось приклад того, як ви могли це зробити. Зауважте, що мене надихнули коментарі в документах ng-повторів: http://jsfiddle.net/digitalzebra/wnWY6/

Зверніть увагу на директиву ng-повторів:

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

8
Ви також можете скористатися _.rangeз Underscore або lodash для створення масиву: $ range.range = _.range (0, n);
вдень

83

Я думаю, що цей jsFiddle з цієї нитки може бути тим, що ви шукаєте.

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

3
читайте далі за посиланням нитки google, і в ньому описано, як можна використовувати "фрагмент". наприклад, group1: items.slice (0,3), group2: items.slice (3,6) тощо
trevorc

7
Ця відповідь призведе до найменшого сліду у ваших контролерів, і я вважаю, що також є кращим кутовий підхід. Відповідь, прийняту ІМО, слід замінити на цю.
Метт Дженсен

1
Це має бути прийнята відповідь (на мою думку) - Найелегантніша, більш переважна нг.
Коді

11
@Cody На жаль, ні це не відповідає на питання. ОП заявляє, що "замість того, щоб завжди перебирати масив" і "вважати $scope.numberрівним 5". Намір полягав у використанні цілої змінної для визначення кількості елементів, а не в жорсткому коді та не заздалегідь визначений масив.
Дан

5
@Cody @ sh0ber ви можете встановити ліміт у своїй області застосування ( $scope.limit = 2) та використовувати його як ...|limitTo:limit- див. Оновлений
скрипт

58

Більш простим підходом було б (наприклад, 5 разів):

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

5
Блискуча. Зрозумілі, короткі та безглузді функції в контролері для повернення нового масиву.
maxathousand

2
Я люблю так.
Раббі Шукі Гур

Оновлено, це було неможливо, коли питання було вперше задано (Кутовий 1.2). Я змінив прийняту відповідь, щоб включити цю. Хороша робота!
Dan

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
Це добре, але зауважте, що підкреслення за замовчуванням не входить у рамки - ви не зможете використовувати його у своєму представленні HTML, не роблячи щось подібне $scope._ = _.
jedd.ahyoung

6
Якщо ви використовуєте лодаш або підкреслення, слід ввести його, $rootScopeщоб його можна було використовувати всюди. Поставте це на свою app.runфункцію відразу після app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Джеремі Моріц

Це була ідеальна відповідь для мене. Це просто і дуже просто. Оскільки я повторював використання змінної, яка мала кількість, мені довелося зробити ng-repeat = "n в _.range (1, count + 1). Дякую за рішення.
Darryl

Я спробував це, і поки _ з'являється в $ rootScope, ng-повторення нічого не робить.
Пол

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>

34

Це дійсно UGLY, але він працює без контролера для цілого чи змінної:

ціле число:

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

змінна:

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

Кращий злом коли-небудь! Спасибі
jannis

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>

Джерело:

Гітуб


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кількість повторень, які мають з’явитися в цьому місці.


1
Я вважаю, що це не дозволяє вам змінювати кількість повторів у HTML, якщо воно змінюється в контролері, якщо тільки ви не вкладете його у функцію, як це робили інші відповіді.
трис

@trysis: Я не впевнений, чи я розумію вашу проблему, але ви повинні замінити repeatCountфактичним числом у HTML, і якщо це число менше, ніж рівне MAX_REPEATS, це дозволить вам встановити число повторів у HTML.
JellicleCat

1
На мою думку, це найелегантніший спосіб обмеження ngRepeatдирективи. Використовуючи Array.prototype.sliceі ідіоматичний JS, слід завжди вибирати таку бібліотеку, як underscore.js (сумісність браузера залежно).
Пат Мільяччо

Непогане рішення, +1, але я вважаю, що ця відповідь простіше, і уникає захаращення контролера.
maxathousand

8

кутовий дає дуже солодку функцію під назвою зріз .. використовуючи це, ви можете досягти того, що шукаєте. наприклад, ng-repe = "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;
}

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

Ось відповідь на кутовий 1.2.x

В основному це те саме, з незначною модифікацією ng-repeat

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

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

це тому, що кутовий 1.2 не дозволяє повторювати значення в директиві. Це означає, що якщо ви намагаєтесь зробити наступне, ви отримаєте помилку.

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

6

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

Отже, якщо число - це кількість разів, коли потрібно повторити елемент:

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

1
Для тих, хто любить чисту розмітку ... Пам’ятайте, що ng-repeatтаким чином все одно виведете коментовані теги ( <!-- ngIf: $index < num -->тощо). Просто liDOM не матиме жодних елементів для відображення. Перевірте "джерело перегляду" на панелі результатів тут, щоб побачити, що я маю на увазі.

3

Ви можете використовувати цей приклад.

Внутрішній контролер:

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

Приклад вибору елемента на стороні 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>

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>

3

Трохи розширивши першу відповідь Івана, ви можете використовувати рядок як колекцію без доріжки за заявою до тих пір, поки символи є унікальними, тому, якщо випадки використання менше 10 чисел, як це питання, я б просто зробив :

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

Це трохи прискіпливо, звичайно, але досить просто, щоб подивитися і не особливо заплутати.


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

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>

я вважаю, що розкол тут непотрібний. рядок - це вже масив символів.
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функцію підкреслення як ми, де вже використовуємо її в проекті, але ви можете легко замінити її нативним кодом.


0

Я створюю директиву для багаторазового використання, де максимальне число виходитиме з іншого ng-повтору. Отже, це редагування найкращої відповіді.

Просто змініть код на контролері на це -

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

Це поверне новий масив із заданою кількістю ітерацій


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елементи без зайвого коду. Скажи '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>

-1

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

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

в компоненті / контролері, а потім:

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

Цей код є з мого проекту машинопису, але його можна буде переставити на чистий JavaScript

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.