Maneira de ng-repita número definido de vezes em vez de repetir sobre matriz?

417

Existe uma maneira de ng-repeatum número definido de vezes, em vez de sempre ter que repetir uma matriz?

Por exemplo, abaixo, quero que o item da lista seja exibido 5 vezes, assumindo $scope.numberigual a 5, além de aumentar o número, de modo que cada item da lista aumente como 1, 2, 3, 4, 5

Resultado desejado:

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

Respostas:

569

Atualização (25/09/2018)

As versões mais recentes do AngularJS (> = 1.3.0) permitem fazer isso apenas com uma variável (nenhuma função é necessária):

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

Isso não foi possível no momento em que a pergunta foi feita pela primeira vez. Agradecemos a @Nikhil Nambiar por sua resposta abaixo para esta atualização


Original (29/5/2013)

No momento, ng-repeatapenas aceita uma coleção como parâmetro, mas você pode fazer isso:

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

E em algum lugar do seu controlador:

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

Isso permitirá que você altere $scope.numberpara qualquer número que desejar e ainda mantenha a ligação que está procurando.

EDIT (1/6/2014) - As versões mais recentes do AngularJS (> = 1.1.5) requerem track by $index:

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

Aqui está um violino com algumas listas usando a mesma getNumberfunção.

Dan
fonte
Estou usando isso para vários itens da lista, mas parece funcionar apenas para a primeira lista. Você sabe por que esse é o caso?
Malcr001
Deve funcionar para qualquer número de listas. Verifique este violino
Dan
1
Obrigado novamente. Esqueci de remover ng-repeat no elemento pai. Está funcionando agora. Obrigado.
Malcr001
3
$ scope.getNumber = function (num) {var x = new Array (); for (var i = 0; i <num; i ++) {x.push (i + 1); } retornar x; } // utilizar esta função quando o número é alterações dinamicamente
Manavendher
1
@ sh0ber. Quando preciso alterar os itens da lista com base no valor selecionado na lista suspensa de números. Tentei sua função primeiro, quando não está funcionando, mudei para acima para atualizar o não. de itens da lista quando um número diferente é selecionado no menu suspenso. Você pode verificar meu cenário usando sua função.
precisa saber é o seguinte
135

você consegue fazer isso:

<div ng-repeat="i in [1, 2, 3, 4]">
  ...
</div>
akonsu
fonte
1
funcionou como um encanto, testado no Chrome v. 39.0.2171.95 (64 bits), FF v. 33.1.1 e Safari v. 8.0.2
Neara
Isso funciona perfeitamente se você o estiver usando em um controle de paginação onde tudo o que você precisa é <li> <a href = "javascript :;" ng-click = "SelectPage ($ index)"> {{i}} </a> </li>
Rick
@AdityaMP, use isso para intervalos em javascript stackoverflow.com/a/31989462/3160597
azerafati
1
Considere chamar o construtor da matriz para uma matriz de comprimento dinâmico, conforme declarado nesta resposta .
maxathousand
e se eu tiver que repetir 120 vezes. Devo ir com [1,2,3 ... 120]?
Munkhdelger Tumenbayar
94

Aqui está um exemplo de como você pode fazer isso. Observe que fui inspirado por um comentário nos documentos ng-repeat: http://jsfiddle.net/digitalzebra/wnWY6/

Observe a diretiva ng-repeat:

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

Aqui está o controlador:

function TestCtrl($scope) {
    $scope.range = function(n) {
        return new Array(n);
    };
};
Polaris878
fonte
8
Você também pode usar _.rangeUnderscore ou lodash para criar a matriz: $ scope.range = _.range (0, n);
tarde
83

Eu acho que este jsFiddle a partir desta discussão pode ser o que você está procurando.

<div ng-app ng-controller="Main">
   <div ng-repeat="item in items | limitTo:2">
       {{item.name}}
   </div>
</div>
jeffmayeur
fonte
3
leia mais abaixo no link do thread do Google e descreve como você pode usar 'fatia'. por exemplo, group1: items.slice (0,3), group2: items.slice (3,6), etc.
trevorc
7
Essa resposta resultará na menor pegada possível em seus controladores e acredito que também seja a abordagem angular preferida. A resposta aceita pela IMO deve ser substituída por esta.
Matt Jensen
1
Esta deve ser a resposta aceita (na minha opinião) - Mais elegante, mais preferida por ng.
Cody
11
@ Cody Infelizmente, não, não responde à pergunta. Os estados OP "em vez de sempre ter que repetir uma matriz" e "assumindo $scope.numberigual a 5". A intenção era usar uma variável inteira para definir a contagem de itens, não codificá-la e não usar uma matriz predefinida.
Dan
5
@Cody @ sh0ber você pode definir o limite em seu escopo ( $scope.limit = 2) e usá-lo como ...|limitTo:limit- veja fiddle atualizados
drzaus
58

Uma abordagem mais simples seria (por exemplo, 5 vezes):

<div ng-repeat="x in [].constructor(5) track by $index">
       ...
</div>
Nikhil Nambiar
fonte
5
Brilhante. Funções legíveis, curtas e inexistentes no controlador para retornar uma nova matriz.
maxathousand
2
Eu amo assim.
Rabino Shuki Gur
Promovido, isso não foi possível quando a pergunta foi feita pela primeira vez (Angular 1.2). Modifiquei a resposta aceita para incluir isso. Bom trabalho!
Dan
1
Eu só queria que eu entendi por que esta sintaxe funciona, mas não Array(5)(ou mesmo [...Array(5).keys()]para obter uma matriz [0,1,2,3,4])
Dylan Nicholson
50

Eu tive o mesmo problema. Me deparei com esse tópico, mas não gostei dos métodos que eles tinham aqui. Minha solução estava usando underscore.js, que já tínhamos instalado. É simples assim:

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

Isso fará exatamente o que você está procurando.

Mark Roach
fonte
27
Isso é bom, mas observe que o Underscore não está no escopo por padrão - você não seria capaz de usá-lo na sua visualização HTML sem fazer algo parecido $scope._ = _.
jedd.ahyoung
6
Se você estiver usando lodash ou sublinhado, coloque-o $rootScopepara que possa ser usado em qualquer lugar. Coloque isso em sua app.runfunção logo após o app.config: app.run(function ($rootScope) { $rootScope._ = _; });
Jeremy Moritz
Essa foi uma resposta perfeita para mim. É simples e muito direto. Desde que eu estava repetindo usando uma variável que tinha uma contagem, tive que fazer ng-repeat = "n em _.range (1, count + 1). Obrigado pela solução."
Darryl
Eu tentei isso e enquanto _ aparece no $ rootScope, o ng-repeat não renderiza nada.
Paul
49

Eu queria manter meu html muito mínimo, então defini um pequeno filtro que cria a matriz [0,1,2, ...] como outros fizeram:

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

Depois disso, na visualização é possível usar assim:

<ul>
  <li ng-repeat="i in 5 | range">
    {{i+1}} <!-- the array will range from 0 to 4 -->
  </li>
</ul>
miguelr
fonte
34

Isso é realmente FEIO, mas funciona sem um controlador para um número inteiro ou variável:

inteiro:

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

variável:

<span ng-repeat="_ in ((_ = []) && (_.length=myVar) && _) track by $index">{{$index}}</span>
MJ
fonte
Melhor hack de todos os tempos! Graças
Jannis
2
_ in (_ = []).length = 33; _ track by $indexUm pouco menor
Fabricio
16

Existem diversas formas de fazer isto. Eu estava realmente preocupado em ter a lógica no meu controlador, então criei uma diretiva simples para resolver o problema de repetir um elemento n vezes.

Instalação:

A diretiva pode ser instalada usando bower install angular-repeat-n

Exemplo:

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

produz: 1234

Também funciona usando uma variável de escopo:

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

Fonte:

Github

connorbode
fonte
1
Isso é algo que deve considerar a adição as directivas oficiais angulares
HarshaXsoad
13

Essa é apenas uma pequena variação na resposta aceita, mas você realmente não precisa criar uma nova função. Apenas para importar 'Matriz' no escopo:

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

Veja este violino para um exemplo ao vivo.

Sylvain Leroux
fonte
4
atualizado (2016) e muito mais limpo!
Julien Malige
9

Resposta mais fácil: 2 linhas de código

JS (no seu controlador 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>

... onde repeatCountestá o número de repetições que devem aparecer neste local.

JellicleCat
fonte
1
Acredito que isso não permita que você altere o número de repetições no HTML se ele for alterado no controlador, a menos que você o envolva em uma função como outras respostas fizeram.
trysis
@trysis: não sei se entendi o seu problema, mas você deve substituir repeatCountpor um número real no HTML e, desde que esse número seja menor ou igual a MAX_REPEATS, isso permitirá que você defina o número de repetições no HTML.
JellicleCat
1
Na minha opinião, esta é a maneira mais elegante de limitar a ngRepeatdiretiva. O uso de Array.prototype.sliceJS idiomático deve sempre ser escolhido em uma biblioteca como underscore.js (dependendo da compatibilidade do navegador).
Pat Migliaccio 23/02
Não é uma solução ruim, +1, mas acho que essa resposta é mais fácil e evita sobrecarregar o controlador.
maxathousand
8

angular fornece uma função muito interessante chamada fatia . Usando isso, você pode conseguir o que está procurando. por exemplo, ng-repeat = "ab em abc.slice (startIndex, endIndex)"

esta demonstração: http://jsfiddle.net/sahilosheal/LurcV/39/ ajudará você e informará como usar essa função "facilitar a vida". :)

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'}];
    }
sheelpriy
fonte
6

Heres uma resposta para angular 1.2.x

Basicamente, é o mesmo, com a ligeira modificação do ng-repeat

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

aqui está o violino: http://jsfiddle.net/cHQLH/153/

isso ocorre porque o angular 1.2 não permite valores duplicados na diretiva. Isso significa que se você estiver tentando fazer o seguinte, receberá um erro.

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

Você pode usar a ng-ifdiretiva comng-repeat

Portanto, se num é o número de vezes que você precisa que o elemento seja repetido:

<li ng-repeat="item in list" ng-if="$index < num">
akaashanky
fonte
1
Para aqueles que gostam de marcação limpa ... Lembre-se de que o uso ng-repeatdessa maneira ainda produzirá as tags comentadas ( <!-- ngIf: $index < num -->etc.). Simplesmente não haverá lielementos para o DOM renderizar. Verifique uma "fonte de exibição" no painel de resultados aqui para ver o que quero dizer.
3

Você pode usar este exemplo.

Controlador interno:

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

Exemplo para o elemento select no lado do código 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
fonte
3

Para usuários que usam o CoffeeScript, você pode usar uma compreensão de intervalo:

Directiva

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

ou Controlador

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

Modelo

<div ng-repeat="i in range">[ the rest of your code ]</div>
Roi
fonte
3

Expandindo um pouco a primeira resposta de Ivan, você pode usar uma string como a coleção sem uma faixa por declaração, desde que os caracteres sejam únicos; portanto, se o caso de uso for menor que 10 números, é a pergunta que eu faria simplesmente :

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

O que é um pouco instável, claro, mas simples o suficiente para ser visto e não particularmente confuso.

omikes
fonte
2

Primeiro, crie um filtro angular usando o LoDash:

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

A função LoDash times é capaz de manipular representação nula, indefinida, 0, números e sequência de números.

Em seguida, use-o no seu HTML como este:

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

ou

<span ng-repeat="i in myVar | times">
 <!--DO STUFF-->
</span>
Karanvir Kang
fonte
1

Eu precisava de uma solução mais dinâmica para isso - onde eu pudesse incrementar a repetição.

HTML

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

Controle do duplicador

<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
fonte
1

Angular fornece filtros para modificar uma coleção. Nesse caso, a coleção seria nula, ou seja, [], e o filtro também recebe argumentos, como a seguir:

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

Esse método é muito semelhante aos propostos acima e não é necessariamente superior, mas mostra o poder dos filtros no AngularJS.

Nik Dow
fonte
1

Se n não for muito alto, outra opção poderia ser usar split ('') com uma sequência de n caracteres:

<div ng-controller="MainCtrl">
<div ng-repeat="a in 'abcdefgh'.split('')">{{$index}}</div>
</div>
vonwolf
fonte
Eu acredito que a divisão é desnecessária aqui. uma string já é uma matriz de caracteres.
omikes
1

Eu encontrei o mesmo problema e foi isso que eu descobri:

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

... e o html:

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

EXEMPLO AO VIVO

Usei a timesfunção de sublinhado como já a usamos no projeto, mas você pode substituí-la facilmente por código nativo.

nicooga
fonte
0

Estou criando uma diretiva reutilizável em que o número máximo virá de outro ng-repeat. Portanto, esta é uma edição da melhor resposta votada.

Apenas mude o código no controlador para isso -

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

Isso retornará uma nova matriz com número especificado de iterações

sagars01
fonte
0

desde que iterou sobre uma string, ele renderizará um item para cada caractere:

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

podemos usar essa solução alternativa feia, mas sem código, usando o number|n decimal placesfiltro nativo.

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

Dessa forma, teremos mynumberelementos sem código extra. Diga '0.000'.
Usamos mynumber - 2para compensar 0.
. Não funcionará para números abaixo de 3, mas pode ser útil em alguns casos.

Ivan Ferrer Villa
fonte
você usou track by $index?
Ivan Ferrer Villa
isso é gueto af. se você vai ser obrigado a ter um char para cada iteração que você pode muito bem fazerng-repeat="i in [1,2,3,4]"
Roi
é claro, mas OP quer a iteração ser n vezes com base em uma variável$scope.number
Ivan Ferrer Villa
por que não 'abcd' em vez de 'aaaa' e depois descarta a trilha?
omikes
aaaafoi um exemplo para explicar minha solução alternativa, não muito elegante. Usando 'aaaa' ou 'abcd' codificado, você obtém uma lista de tamanho fixo, mas adicionando mynumber-2decimais a 0, obtém uma 'string' com mynumbercaracteres. Digamos mynumber=5, entendemos '0.000', e iteramos isso usando o índice $
Ivan Ferrer Villa
0
$scope.number = 5;

<div ng-repeat="n in [] | range:$scope.number">
      <span>{{$index}}</span>
</div>
Idiota
fonte
-1

maneira simples:

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

no componente / controlador e, em seguida:

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

Este código é do meu projeto datilografado, mas pode ser reorganizado para javascript puro

Pallepassion
fonte