@Component({
(...)
template: `
<div *ngFor="let i of Arr(num).fill(1)"></div>
`
})
export class SomeComponent {
Arr = Array; //Array type captured in a variable
num:number = 20;
}
Ou implemente um tubo personalizado:
import {PipeTransform, Pipe} from '@angular/core';
@Pipe({
name: 'fill'
})
export class FillPipe implements PipeTransform {
transform(value) {
return (new Array(value)).fill(1);
}
}
@Component({
(...)
template: `
<div *ngFor="let i of num | fill"></div>
`,
pipes: [ FillPipe ]
})
export class SomeComponent {
arr:Array;
num:number = 20;
}
Esta deve ser a resposta correta. É de longe a mais concisa!
Mantisimo
ERROR RangeError: Comprimento de array inválido. Isso irá travar quando o número de gatos a desenhar for zero.
Tom Bevelander
Realmente gosto dessa abordagem simples!
F. Geißler
51
Existem dois problemas com as soluções recomendadas usando Arrays:
É um desperdício. Em particular para grandes números.
Você tem que defini-los em algum lugar, o que resulta em muita desordem para uma operação tão simples e comum.
Parece mais eficiente definir um Pipe(uma vez), retornando um Iterable:
import {PipeTransform, Pipe} from '@angular/core';
@Pipe({name: 'times'})
export class TimesPipe implements PipeTransform {
transform(value: number): any {
const iterable = <Iterable<any>> {};
iterable[Symbol.iterator] = function* () {
let n = 0;
while (n < value) {
yield ++n;
}
};
return iterable;
}
}
Exemplo de uso (renderização de uma grade com largura / altura dinâmica):
<table>
<thead>
<tr>
<th *ngFor="let x of colCount|times">{{ x }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let y of rowCount|times">
<th scope="row">{{ y }}</th>
<td *ngFor="let x of colCount|times">
<input type="checkbox" checked>
</td>
</tr>
</tbody>
</table>
OP disse que atribuiu 20a uma variável de membro .. então isso não vai ajudar muito
phil294
E se eu quiser iterar 200 vezes?
Chax
1
@Chax Você não pode. :(
Muhammad bin Yusrat
2
@Chax O que há de errado com 200? *ngFor="let number of [0,1,2,3,4,5...,199,200]":-D
Stack Underflow
1
@StackUnderflow Infelizmente, não sou pago por personagens. Se eu fosse, pregaria que essa é a única maneira de conseguir isso: P (sério, simplesmente não faça;))
Chax
10
Uma solução mais simples e reutilizável talvez seja usar uma diretiva estrutural personalizada como esta.
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appTimes]'
})
export class AppTimesDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set appTimes(times: number) {
for (let i = 0 ; i < times ; i++) {
this.viewContainer.createEmbeddedView(this.templateRef);
}
}
}
A maneira mais eficiente e concisa de conseguir isso é adicionando um utilitário iterador. Não se preocupe em ceder valores. Não se preocupe em definir uma variável na diretiva ngFor:
function times(max: number) {
return {
[Symbol.iterator]: function* () {
for (let i = 0; i < max; i++, yield) {
}
}
};
}
@Component({
template: ```
<ng-template ngFor [ngForOf]="times(6)">
repeats 6 times!
</ng-template>
```
})
export class MyComponent {
times = times;
}
Declare uma variável de membro dentro do componente para fazer referência a Lodash.
lodash = _;
Então, em sua visão, você pode usar a função de intervalo . 20 pode ser substituído por qualquer variável em seu componente.
*ngFor="let number of lodash.range(20)"
Deve-se dizer que vincular a funções na visualização pode ser caro, dependendo da complexidade da função que você está chamando, pois a Detecção de Mudança chamará a função repetidamente.
Você não precisa preencher a matriz como sugerido na maioria das respostas. Se você usar o índice em seu ngForloop, tudo o que você precisa criar é uma matriz vazia com o comprimento correto:
const elements = Array(n); // n = 20 in your case
e na sua opinião:
<li *ngFor="let element in elements; let i = index">
<span>{{ i }}</span>
</li>
Defina um helperArray e instancie-o dinamicamente (ou estático, se desejar) com o comprimento da contagem que você deseja para criar seus elementos HTML. Por exemplo, desejo obter alguns dados do servidor e criar elementos com o comprimento do array que é retornado.
Sei que você pediu especificamente para fazer isso usando * ngFor, mas gostaria de compartilhar a maneira como resolvi isso usando uma diretiva estrutural:
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[appRepeat]' })
export class RepeatDirective {
constructor(private templateRef: TemplateRef<any>, private viewContainerRef: ViewContainerRef) {
}
@Input() set appRepeat(loops: number) {
for (let index = 0; index < loops; ++index) {
this.viewContainerRef.createEmbeddedView(this.templateRef);
}
}
}
Respostas:
Você pode usar o seguinte:
Ou implemente um tubo personalizado:
fonte
arr=Array;
?Substitua
20
pela sua variávelfonte
gera 🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
fonte
Existem dois problemas com as soluções recomendadas usando
Arrays
:Parece mais eficiente definir um
Pipe
(uma vez), retornando umIterable
:Exemplo de uso (renderização de uma grade com largura / altura dinâmica):
fonte
Você pode fazer isso simplesmente em seu HTML:
E use a variável "número" para indexar.
fonte
20
a uma variável de membro .. então isso não vai ajudar muito*ngFor="let number of [0,1,2,3,4,5...,199,200]"
:-DUma solução mais simples e reutilizável talvez seja usar uma diretiva estrutural personalizada como esta.
E use-o assim:
fonte
A maneira mais eficiente e concisa de conseguir isso é adicionando um utilitário iterador. Não se preocupe em ceder valores. Não se preocupe em definir uma variável na diretiva ngFor:
fonte
Se estiver usando Lodash , você pode fazer o seguinte:
Importe Lodash em seu componente.
Declare uma variável de membro dentro do componente para fazer referência a Lodash.
Então, em sua visão, você pode usar a função de intervalo . 20 pode ser substituído por qualquer variável em seu componente.
Deve-se dizer que vincular a funções na visualização pode ser caro, dependendo da complexidade da função que você está chamando, pois a Detecção de Mudança chamará a função repetidamente.
fonte
Você não precisa preencher a matriz como sugerido na maioria das respostas. Se você usar o índice em seu
ngFor
loop, tudo o que você precisa criar é uma matriz vazia com o comprimento correto:e na sua opinião:
fonte
Abordagem mais simples:
Defina um helperArray e instancie-o dinamicamente (ou estático, se desejar) com o comprimento da contagem que você deseja para criar seus elementos HTML. Por exemplo, desejo obter alguns dados do servidor e criar elementos com o comprimento do array que é retornado.
Em seguida, use o helperArray em meu modelo HTML.
fonte
Esta é uma versão ligeiramente melhorada da diretiva estrutural de Ilyass Lamrani que permite usar o índice em seu modelo:
Uso:
fonte
Sei que você pediu especificamente para fazer isso usando * ngFor, mas gostaria de compartilhar a maneira como resolvi isso usando uma diretiva estrutural:
Com isso, você pode usá-lo assim:
fonte
Você pode usar isso simplesmente:
HTML
TS
fonte