2016-04-01 4 views
67

... к примеру ...Угловое 2 - NgFor с использованием номеров вместо коллекций

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

?

+4

У меня такая же проблема. Действительно расстроен, нельзя делать такие простые вещи с угловыми 2. – albanx

ответ

59

В рамках компонента, вы можете определить массив чисел (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 way to create an array of integers from 1..20 in 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 { 
    (...) 
} 
+3

Да, Тьерри! Это не ваша вина, действительно, но все же в одном и том же контексте :(Это совсем не элегантно. Но поскольку вы очень опытный разработчик A2, я могу предположить, что лучшего решения нет. Печально! –

+0

На самом деле, есть ничего для этого в Angular2 в синтаксисе цикла. Вам нужно использовать то, что JavaScript предоставляет для сборки массивов. Например: 'Array (5) .fill (4)' to create '[4,4,4,4,4]' –

+3

PS: аннотация @View была удалена в angular2 beta 10 и выше. –

46

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

Использование трубы

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> 

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

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

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

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

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

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

Здесь работает демо для того же -

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

+3

Вы также можете использовать метод 'Array.fill()' для генерации массива вместо 'res.push()', как показано в ответе Тьерриса. –

+0

Да, я могу, но что-то не так с 'push'? Я имею в виду, что оба метода верны, но все же, если какой-либо diff. между ними. –

+3

Нет, все еще хорошее решение +1. Я просто нахожу 'Array.fill()' более элегантным, чем цикл, используя push, и это также, вероятно, более эффективно. –

8

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

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

+0

Я согласен, что подход массива уродлив, но для меня это кажется преждевременной оптимизацией. –

+3

Конечно, но и упражнение в написании директивы. С другой стороны, это не длиннее трубы, что было бы вторым разумным подходом. – pdudits

+0

Это хороший момент, у вас не так много возможностей получить некоторые из них с концепцией пользовательских структурных директив. –

2

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

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

0

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

Распределение необходимых переменных:

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

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

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

Смежные вопросы