web-dev-qa-db-fra.com

Angular 2 - NgFor utilisant des nombres à la place des collections

...par exemple...

<div class="month" *ngFor="#item of myCollection; #i = index">
...
</div>

Est-il possible de faire quelque chose comme ...

<div class="month" *ngFor="#item of 10; #i = index">
...
</div>

... sans faire appel à une solution non élégante comme:

<div class="month" *ngFor="#item of ['dummy','dummy','dummy','dummy','dummy',
'dummy','dummy','dummy']; #i = index">
...
</div>

?

124
Marco Jr

Dans votre composant, vous pouvez définir un tableau de nombres (ES6) comme décrit ci-dessous:

export class SampleComponent {
  constructor() {
    this.numbers = Array(5).fill().map((x,i)=>i); // [0,1,2,3,4]
    this.numbers = Array(5).fill(4); // [4,4,4,4,4]
  }
}

Voir ce lien pour la création de tableau: Tersest moyen de créer un tableau d’entiers de 1..20 en JavaScript .

Vous pouvez ensuite parcourir ce tableau avec ngFor:

@Component({
  template: `
    <ul>
      <li *ngFor="let number of numbers">{{number}}</li>
    </ul>
  `
})
export class SampleComponent {
  (...)
}

Ou sous peu:

@Component({
  template: `
    <ul>
      <li *ngFor="let number of [0,1,2,3,4]">{{number}}</li>
    </ul>
  `
})
export class SampleComponent {
  (...)
}
133
Thierry Templier

Non, il n'y a pas encore de méthode pour NgFor qui utilise des nombres à la place des collections, Pour le moment, * ngFor n'accepte qu'une collection en tant que paramètre, mais vous pouvez le faire en appliquant les méthodes suivantes:

À l'aide d'un tuyau

pipe.ts

import {Pipe, PipeTransform} from 'angular2/core';

@Pipe({name: 'demoNumber'})
export class DemoNumber implements PipeTransform {
  transform(value, args:string[]) : any {
    let res = [];
    for (let i = 0; i < value; i++) {
        res.Push(i);
      }
      return res;
  }
}


<ul>
  <li>Method First Using PIPE</li>
  <li *ngFor='#key of 5 | demoNumber'>
    {{key}}
  </li>
</ul>

Utiliser un tableau de nombres directement en HTML (View)

<ul>
  <li>Method Second</li>
  <li *ngFor='#key of  [1,2]'>
    {{key}}
  </li>
</ul>

Utiliser la méthode Split

<ul>
  <li>Method Third</li>
  <li *ngFor='#loop2 of "0123".split("")'>{{loop2}}</li>
</ul>

Utilisation de la création d'un nouveau tableau dans le composant

<ul>
  <li>Method Fourth</li>
  <li *ngFor='#loop3 of counter(5) ;#i= index'>{{i}}</li>
</ul>

export class AppComponent {
  demoNumber = 5 ;

  counter = Array;

  numberReturn(length){
    return new Array(length);
  }
}

Démo de travail

57
Pardeep Jain

Je ne pouvais pas supporter l'idée d'allouer un tableau pour la répétition simple de composants, alors j'ai écrit une directive structurelle. Dans la forme la plus simple, cela ne rend pas l'index disponible pour le modèle, cela ressemble à ceci:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({ selector: '[biRepeat]' })
export class RepeatDirective {

  constructor( private templateRef: TemplateRef<any>,
             private viewContainer: ViewContainerRef) { }

  @Input('biRepeat') set count(c:number) {
    this.viewContainer.clear();
    for(var i=0;i<c;i++) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    }
  }
}

http://plnkr.co/edit/bzoNuL7w5Ub0H5MdYyFR?p=preview

10
pdudits

@OP, vous étiez terriblement proches de votre solution "non élégante".

Que diriez-vous:

<div class="month" *ngFor="let item of [].constructor(10); let i = index"> ... </div>

Ici, le constructeur Array provient d'un tableau vide: [].constructor, car Array n'est pas un symbole reconnu dans la syntaxe du modèle, et je suis trop paresseux pour faire Array=Array ou counter = Array dans le composant TypeScript comme l'a fait @ pardeep-jain son 4ème exemple. Et je l’appelle sans new car new n’est pas nécessaire pour obtenir un tableau dans le constructeur Array.

Array(30) et new Array(30) sont équivalents.

Le tableau sera vide, mais cela n'a pas d'importance car vous voulez simplement utiliser i à partir de ;let i = index dans votre boucle.

10
jcairney

Je l'ai résolu comme ça en utilisant Angular 5.2.6 et TypeScript 2.6.2:

class Range implements Iterable<number> {
    constructor(
        public readonly low: number,
        public readonly high: number,
        public readonly step: number = 1
    ) {
    }

    *[Symbol.iterator]() {
        for (let x = this.low; x <= this.high; x += this.step) {
            yield x;
        }
    }
}

function range(low: number, high: number) {
    return new Range(low, high);
}

Il peut être utilisé dans un composant comme celui-ci:

@Component({
    template: `<div *ngFor="let i of r">{{ i }}</div>`
})
class RangeTestComponent {
    public r = range(10, 20);
}

Vérification d'erreur et assertions omises volontairement par souci de brièveté (par exemple, que se passe-t-il si l'étape est négative)?.

4
Per Edin

Vous pouvez utiliser lodash:

@Component({
  selector: 'board',
  template: `
<div *ngFor="let i of range">
{{i}}
</div>
`,
  styleUrls: ['./board.component.css']
})
export class AppComponent implements OnInit {
  range = _.range(8);
}

Je n'ai pas testé le code mais cela devrait fonctionner.

3
Alex Po

vous pouvez aussi utiliser comme ça

export class SampleComponent {
   numbers:Array<any> = [];
   constructor() {
      this.numbers = Array.from({length:10},(v,k)=>k+1);
   }
}

HTML

<p *ngFor="let i of numbers">
   {{i}}
</p>
1
Tonmoy Nandy

Un moyen simple que j'ai essayé

Vous pouvez également créer un tableau dans votre fichier de composant et l'appeler avec la directive * ngFor en renvoyant sous forme de tableau.

Quelque chose comme ça ....

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-morning',
  templateUrl: './morning.component.html',
  styleUrls: ['./morning.component.css']
})
export class MorningComponent implements OnInit {

  arr = [];
  i: number = 0;
  arra() {
    for (this.i = 0; this.i < 20; this.i++) {
      this.arr[this.i]=this.i;
    }
    return this.arr;
  }

  constructor() { }

  ngOnInit() {
  }

}

Et cette fonction peut être utilisée dans votre fichier de modèle html

<p *ngFor="let a of arra(); let i= index">
value:{{a}} position:{{i}}
</p>
0
Alok Panday

Veuillez trouver en pièce jointe ma solution dynamique si vous souhaitez augmenter la taille d'un tableau de manière dynamique après avoir cliqué sur un bouton (c'est ainsi que je suis arrivé à cette question).

Affectation des variables nécessaires:

  array = [1];
  arraySize: number;

Déclarez la fonction qui ajoute un élément au tableau:

increaseArrayElement() {
   this.arraySize = this.array[this.array.length - 1 ];
   this.arraySize += 1;
   this.array.Push(this.arraySize);
   console.log(this.arraySize);
}

Invoquer la fonction en HTML

  <button md-button (click)="increaseArrayElement()" >
      Add element to array
  </button>

Itérer dans tableau avec ngFor:

<div *ngFor="let i of array" >
  iterateThroughArray: {{ i }}
</div>
0

Ma solution:

export class DashboardManagementComponent implements OnInit {
  _cols = 5;
  _rows = 10;
  constructor() { }

  ngOnInit() {
  }

  get cols() {
    return Array(this._cols).fill(null).map((el, index) => index);
  }
  get rows() {
    return Array(this._rows).fill(null).map((el, index) => index);
  }

En html:

<div class="charts-setup">
  <div class="col" *ngFor="let col of cols; let colIdx = index">
    <div class="row" *ngFor="let row of rows; let rowIdx = index">
      Col: {{colIdx}}, row: {{rowIdx}}
    </div>
  </div>
</div>
0
cuddlemeister

Étant donné que la méthode fill ((mentionnée dans la réponse acceptée) sans arguments lance une erreur, je suggérerais quelque chose comme ceci (fonctionne pour moi, Angular 7.0.4, TypeScript 3.1.6)

<div class="month" *ngFor="let item of items">
...
</div>

En code composant:

this.items = Array.from({length: 10}, (v, k) => k + 1);
0
Dalibor