Angular 2 - NgFor ใช้ตัวเลขแทนการรวบรวม


191

...ตัวอย่างเช่น...

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

?


8
ผมมีปัญหาเดียวกัน. จริงๆไม่พอใจอย่างใดอย่างหนึ่งไม่สามารถทำสิ่งที่ง่ายดังกล่าวกับเชิงมุม 2
albanx

1
อาจเป็นประโยชน์: stackoverflow.com/questions/3895478/…
Pizzicato

คำตอบ:


197

ภายในองค์ประกอบของคุณคุณสามารถกำหนดจำนวนอาร์เรย์ (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 {
  (...)
}

5
ใช่แล้ว! ไม่ใช่ความผิดของคุณ แต่ยังอยู่ในบริบทเดียวกัน :( มันไม่ได้หรูหราเลย แต่เนื่องจากคุณเป็นนักพัฒนา A2 ที่เก่งมากฉันจึงสามารถสรุปได้ว่าไม่มีทางออกที่ดีกว่านี้มันน่าเศร้า!
Marco Jr

อันที่จริงไม่มีอะไรสำหรับสิ่งนี้ใน Angular2 ในไวยากรณ์วนซ้ำ คุณต้องใช้ประโยชน์จากสิ่งที่ JavaScript จัดเตรียมไว้เพื่อสร้างอาร์เรย์ ตัวอย่างเช่น: Array(5).fill(4)เพื่อสร้าง[4,4,4,4,4]
Thierry Templier

3
PS: คำอธิบายประกอบ @View ถูกลบใน angular2 เบต้า 10 ขึ้นไป
Pardeep Jain

23
ใช้Array.fill()ใน Angular 2 Typescript ก่อให้เกิดข้อผิดพลาดดังต่อไปนี้Supplied parameters do not match any signature of call t arget.- การตรวจสอบเอกสาร Array.prototype.fill มันบอกว่ามันต้องมี 1 อาร์กิวเมนต์ ... developer.mozilla.org/en/docs/Web/JavaScript/Reference/
Joshua Russell

5
Array(5).fill(1).map((x, i) => i + 1); /*[1,2,3,4,5]*/สิ่งนี้จะช่วยแก้ไขข้อผิดพลาดใน TS
mshahbazm

90

@OP คุณสนิทกับโซลูชัน "ไม่หรูหรา" มาก

เกี่ยวกับ:

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

ที่นี่ฉันได้รับตัวArrayสร้างจากอาเรย์ที่ว่างเปล่า: [].constructorเพราะArrayไม่ใช่สัญลักษณ์ที่รู้จักในไวยากรณ์เทมเพลตและฉันขี้เกียจเกินไปที่จะทำArray=Arrayหรือcounter = Arrayในส่วนประกอบแบบอักษรประกอบเช่น @ pardeep-jain ทำในตัวอย่างที่ 4 ของเขา และฉันเรียกมันโดยไม่ต้องnewเพราะnewไม่จำเป็นสำหรับการอาร์เรย์ออกArrayคอนสตรัค

Array(30)และnew Array(30)เทียบเท่า

อาร์เรย์จะว่างเปล่า แต่นั่นไม่สำคัญเพราะคุณเพียงต้องการใช้iจาก;let i = indexในวงวนของคุณ


12
นี่คือคำตอบที่ดีที่สุด
kagronick

วิธีนี้ทำให้เกิดการตรวจจับการเปลี่ยนแปลง ฉันเดาว่าเนื่องจากอาร์เรย์ใหม่
Tobias81

1
@ Tobias81 คุณช่วยอธิบายได้ไหม? คุณกำลังบอกว่าทุกครั้งที่แอปทำการตรวจจับการเปลี่ยนแปลงเนื้อหาของ * ngFor จะถูกวาดขึ้นมาใหม่เนื่องจากมีการสร้างอาร์เรย์ขึ้นมาใหม่หรือไม่ นั่นเป็นสิ่งที่ควรค่าแก่การสังเกต ใคร ๆ ก็สามารถทำได้โดยการสร้างเขตข้อมูลอาเรย์ใน TS เพื่ออ้างอิงดังนั้นมันจึงเหมือนกันทุกครั้งที่การตรวจจับการเปลี่ยนแปลงทำงาน แต่นั่นจะไม่สวยงามเกินกว่าที่ต้องการแน่นอน ปัญหาการตรวจจับการเปลี่ยนแปลงเดียวกันมีอยู่ในตัวอย่างที่ 2 ในคำตอบที่เลือกของ Thierry Templier หรือไม่? <li *ngFor="let number of [0,1,2,3,4]">{{number}}</li>
jcairney

นี่เป็นทางออกที่ดีที่สุดสำหรับปัญหานี้
khush

1
@ Tobias81 ฉันได้ตรวจสอบเพื่อให้แน่ใจว่าการตรวจจับการเปลี่ยนแปลงไม่ได้สร้างเนื้อหาของ ngFor ซ้ำ ๆ โดยใส่คำสั่งการพิมพ์ไว้ในตัวสร้างของส่วนประกอบที่ฉันสร้างขึ้นเป็นตัวอย่างของคำสั่ง ngFor ฉันไม่เห็นส่วนประกอบที่ถูกสร้างใหม่ในการวนซ้ำการตรวจจับการเปลี่ยนแปลงทุกครั้งดังนั้นฉันจึงไม่คิดว่าจะมีปัญหา (อย่างน้อยใน Angular 8)
jcairney

83

ยังไม่มีวิธีสำหรับ 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='let key of 5 | demoNumber'>
    {{key}}
  </li>
</ul>

การใช้อาร์เรย์ตัวเลขโดยตรงใน HTML (ดู)

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

ใช้วิธีการแยก

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

สาธิตการทำงาน


4
คุณยังสามารถใช้Array.fill()วิธีการสร้างอาร์เรย์แทนที่จะเป็นres.push()แบบที่แสดงในคำตอบของ Thierrys
GünterZöchbauer

ใช่ฉันทำได้ แต่มีอะไรผิดปกติpushหรือไม่? ฉันหมายความว่าทั้งสองวิธีนั้นถูกต้อง แต่ก็ยังต่างกัน ระหว่างพวกเขา.
Pardeep Jain

3
ไม่ยังเป็นทางออกที่ดี +1 ฉันเพิ่งค้นพบความArray.fill()สง่างามยิ่งกว่าลูปที่ใช้การพุชและอาจมีประสิทธิภาพมากกว่า
GünterZöchbauer

1
ฉันชอบวิธีนี้ด้วยcounter = Arrayฉลาดมาก;)
Verri

11

ฉันทนไม่ได้กับความคิดในการจัดสรรอาเรย์สำหรับการทำซ้ำส่วนประกอบแบบธรรมดาดังนั้นฉันจึงเขียนคำสั่งโครงสร้าง ในรูปแบบที่ง่ายที่สุดที่ไม่ทำให้ดัชนีพร้อมใช้งานสำหรับเทมเพลตดูเหมือนว่า:

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


ฉันเห็นด้วยกับวิธีการเรียงลำดับที่น่าเกลียด แต่ดูเหมือนว่าการเพิ่มประสิทธิภาพก่อนวัยอันควรสำหรับฉัน
Aluan Haddad

3
แน่นอน แต่ยังมีการออกกำลังกายในการเขียนคำสั่ง ในอีกทางหนึ่งมันไม่ได้ยาวกว่าท่อซึ่งจะเป็นวิธีที่สองมีสติ
pdudits

นั่นเป็นจุดที่ดีมีโอกาสไม่มากที่จะได้รับบางส่วนของคุณด้วยแนวคิดของคำสั่งโครงสร้างที่กำหนดเอง
Aluan Haddad

Nice one @pdudits - ยังคงใช้งานได้กับเวอร์ชันล่าสุด: plnkr.co/edit/8wJtkpzre3cBNokHcDL7?p=preview [ โปรดอย่าลังเลที่จะอัปเดต plnkr ของคุณ]
AT

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

การตรวจสอบข้อผิดพลาดและการยืนยันไม่ถูกต้องตามวัตถุประสงค์เพื่อความกระชับ


2
มีวิธีใดใน html ตามที่<div *ngfor="let i of 4, i++"></div>ควรจะเป็น
Nithila Shanmugananthan

5

คุณสามารถใช้เช่นนั้น

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>

4

คุณสามารถใช้ 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);
}

ฉันไม่ได้ทดสอบโค้ด แต่ควรใช้งานได้


มีวิธีใดใน html ที่<div *ngfor="let i of 4, i++"></div>อาจจะเป็น
Nithila Shanmugananthan

หากคุณต้องการiหรือจัดทำดัชนีในโค้ดคุณสามารถทำได้*ngFor="let i of range; let i = index"
Alex Po


2

เนื่องจากวิธีการเติม () (กล่าวถึงในคำตอบที่ยอมรับ) โดยไม่มีข้อโต้แย้งที่ทำให้เกิดข้อผิดพลาดฉันจะแนะนำบางอย่างเช่นนี้ (เหมาะสำหรับฉัน, 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);

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

นี่เป็นวิธีที่ดีและรวดเร็วในการทำซ้ำสำหรับจำนวนครั้งใน myCollection

ดังนั้นหาก myCollection เท่ากับ 5, Hello World จะถูกทำซ้ำ 5 ครั้ง


1

การใช้โครงสร้าง Directive ที่กำหนดเองกับดัชนี:

ตามเอกสารเชิงมุม:

createEmbeddedView สร้างมุมมองที่ฝังไว้ในอินสแตนซ์และแทรกลงในคอนเทนเนอร์นี้

abstract createEmbeddedView(templateRef: TemplateRef, context?: C, index?: number): EmbeddedViewRef.

Param          Type           Description
templateRef    TemplateRef    the HTML template that defines the view.
context        C              optional. Default is undefined.
index          number         the 0-based index at which to insert the new view into this container. If not specified, appends the new view as the last entry.

เมื่อเชิงมุมสร้างแม่แบบโดยการเรียก createEmbeddedView ng-templateก็ยังสามารถส่งผ่านบริบทที่จะใช้ภายใน

การใช้พารามิเตอร์ทางเลือกบริบทคุณสามารถใช้ในส่วนประกอบโดยแยกออกมาในเทมเพลตเช่นเดียวกับที่คุณใช้กับ * ngFor

app.component.html:

<p *for="number; let i=index; let c=length; let f=first; let l=last; let e=even; let o=odd">
  item : {{i}} / {{c}}
  <b>
    {{f ? "First,": ""}}
    {{l? "Last,": ""}}
    {{e? "Even." : ""}}
    {{o? "Odd." : ""}}
  </b>
</p>

for.directive.ts:

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

class Context {
  constructor(public index: number, public length: number) { }
  get even(): boolean { return this.index % 2 === 0; }
  get odd(): boolean { return this.index % 2 === 1; }
  get first(): boolean { return this.index === 0; }
  get last(): boolean { return this.index === this.length - 1; }
}

@Directive({
  selector: '[for]'
})
export class ForDirective {
  constructor(private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef) { }

  @Input('for') set loop(num: number) {
    for (var i = 0; i < num; i++)
      this.viewContainer.createEmbeddedView(this.templateRef, new Context(i, num));
  }
}

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>

มีวิธีใดใน html ตามที่<div *ngfor="let i of 4, i++"></div>ควรจะเป็น
Nithila Shanmugananthan

คุณต้องวนซ้ำแถวลำดับ หากคุณต้องการสเกลาร์คุณสามารถทำซ้ำอาร์เรย์ด้วยขนาดที่เหมาะสมและยกตัวอย่างสเกลาร์เพิ่มเติม: * ngFor = "ปล่อยไอเท็มของอาร์เรย์ให้ i = ดัชนี"
Jan Clemens Stoffregen

0

วิธีที่ง่ายที่สุดที่ฉันได้ลอง

นอกจากนี้คุณยังสามารถสร้างอาร์เรย์ในไฟล์คอมโพเนนต์ของคุณและคุณสามารถเรียกมันได้ด้วย * ngFor directive โดยกลับมาเป็นอาร์เรย์

บางสิ่งเช่นนี้ ....

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>

2
มีวิธีใดใน html ตามที่<div *ngfor="let i of 4, i++"></div>ควร
Nithila Shanmugananthan

0

ทางออกของฉัน:

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>

สิ่งนี้สร้าง Array ใหม่ทุกครั้งที่ได้รับ สามารถสร้างค่าใช้จ่าย
Remco Vlierman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.