Angular 2 - NgДля использования чисел вместо коллекций

... например...

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

Можно сделать что-то вроде...

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

... без привлечения нестандартного решения, например:

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

?

Ответ 1

Внутри вашего компонента вы можете определить массив числа (ES6), как описано ниже:

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

См. эту ссылку для создания массива: Tersest способ создания массива целых чисел от 1..20 в JavaScript.

Затем вы можете перебрать этот массив с помощью ngFor:

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

Или коротко:

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

Ответ 2

Нет, пока нет никакого способа для NgFor использовать числа вместо коллекций, На данный момент * ngFor принимает коллекцию только как параметр, но вы можете сделать это следующими способами:

Использование pipes

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='let key of 5 | demoNumber'>
    {{key}}
  </li>
</ul>

Использование массива чисел непосредственно в HTML (просмотр)

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

Использование метода Split

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

Использование создания нового массива в компоненте

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

export class AppComponent {
  demoNumber = 5 ;

  counter = Array;

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

Рабочая демонстрация

Ответ 3

@OP, вы были очень близки со своим "не элегантным" решением.

Как насчет:

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

Здесь я получаю конструктор Array из пустого массива: [].constructor, потому что Array не является распознанным символом в синтаксисе шаблона, и мне лень делать Array=Array или counter = Array в [].constructor компонента как @pardeep-jain сделал в своем 4-м примере. И я называю это без new потому что new не нужно для получения массива из конструктора Array.

Array(30) и new Array(30) эквивалентны.

Массив будет пустым, но это не имеет значения, потому что вы действительно хотите использовать i from ;let я = index в вашем цикле.

Ответ 4

Я не мог нести идею выделения массива для простого повторения компонентов, поэтому я написал структурную директиву. В простейшей форме это не делает индекс доступным для шаблона, он выглядит так:

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

Ответ 5

Я решил это, используя Angular 5.2.6 и 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);
}

Это может быть использовано в компоненте, как это:

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

Проверка на ошибки и утверждения специально для краткости опущены (например, что происходит, если шаг отрицательный).

Ответ 6

Вы можете использовать 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);
}

Я не тестировал код, но он должен работать.

Ответ 7

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

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>

Ответ 8

Поскольку метод fill() (упомянутый в принятом ответе) без аргументов выдает ошибку, я бы предложил что-то вроде этого (работает для меня, Angular 7.0.4, Typescript 3.1.6)

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

В коде компонента:

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

Ответ 9

Если вы хотите увеличить размер массива динамически после нажатия на кнопку, найдите прилагаемое мое динамическое решение (вот как я дошел до этого вопроса).

Выделение необходимых переменных:

  array = [1];
  arraySize: number;

Объявить функцию, которая добавляет элемент в массив:

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

Вызвать функцию в html

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

Итерацию через массив с помощью ngFor:

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

Ответ 10

Самый простой способ, который я пробовал

Вы также можете создать массив в вашем компонентном файле и вызывать его с помощью директивы * ngFor, возвращая в виде массива.

Что-то вроде этого....

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

}

И эта функция может быть использована в вашем файле шаблона HTML

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

Ответ 11

Мое решение:

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

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

Ответ 12

Это также может быть достигнуто следующим образом:

HTML:

<div *ngFor="let item of fakeArray(10)">
     ...
</div>

Машинопись:

fakeArray(length: number): Array<any> {
  if (length >= 0) {
    return new Array(length);
  }
}

Рабочая демонстрация

Ответ 13

<div *ngFor="let number of [].constructor(myCollection)">
    <div>
        Hello World
    </div>
</div>

Это хороший и быстрый способ повторять количество раз в myCollection.