कोणीय 2 - NgFor संग्रह के बजाय संख्याओं का उपयोग करना


190

...उदाहरण के लिए...

<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 के साथ ऐसी सरल बातें नहीं कर सकता है
अल्बानक्स

1
शायद यह मददगार हो सकता है: stackoverflow.com/questions/3895478/…
Pizzicato

जवाबों:


195

अपने घटक के भीतर, आप नीचे वर्णित अनुसार संख्या की संख्या (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]
  }
}

सरणी निर्माण के लिए इस लिंक को देखें: जावास्क्रिप्ट में 1..20 से पूर्णांकों की एक सरणी बनाने का सबसे आसान तरीका

इसके बाद आप इस सरणी पर पुनरावृति कर सकते हैं 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 डेवलपर हैं, मैं मान सकता हूं कि कोई बेहतर समाधान नहीं है। यह दुख की बात है!
मार्को जूनियर

वास्तव में, लूप सिंटैक्स में Angular2 में इसके लिए कुछ भी नहीं है। जावास्क्रिप्ट का निर्माण करने के लिए जावास्क्रिप्ट क्या प्रदान करता है इसका आपको लाभ उठाने की आवश्यकता है। उदाहरण के लिए: Array(5).fill(4)बनाने के लिए[4,4,4,4,4]
थियरी टेम्पलर

3
PS: @ दृश्य एनोटेशन को कोणीय 2 बीटा 10 और इसके बाद के संस्करण में हटा दिया गया है।
प्रदीप जैन

23
का उपयोग करते हुए Array.fill()कोणीय 2 टाइपप्रति में निम्न त्रुटि पैदा करता Supplied parameters do not match any signature of call t arget.Array.prototype.fill डॉक्स जाँच हो रही है, यह कहना है कि वह 1 तर्क की आवश्यकता ... - developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
यहोशू रसेल

5
Array(5).fill(1).map((x, i) => i + 1); /*[1,2,3,4,5]*/यह टीएस में त्रुटि का समाधान करता है
mshahbazm

85

@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


11
यह सबसे अच्छा जवाब है।
कागरिकिक

यह समाधान परिवर्तन का पता लगाने को ट्रिगर करता है। मुझे लगता है कि नए ऐरे के कारण।
तोबियस 81१

1
@ Tobias81, क्या आप विस्तृत कर सकते हैं? क्या आप कह रहे हैं कि हर बार ऐप परिवर्तन का पता लगाता है, तो * ngFor की सामग्री को फिर से तैयार किया जाता है क्योंकि सरणी को फिर से बनाया जाता है? यह निश्चित रूप से ध्यान देने योग्य है। वास्तव में TS के संदर्भ में एक सरणी फ़ील्ड बनाकर कोई भी इसके चारों ओर प्राप्त कर सकता है, इसलिए यह हर बार परिवर्तन का पता लगाने वाले रन के समान है। लेकिन यह निश्चित रूप से वांछित से कम सुरुचिपूर्ण होगा। वही परिवर्तन का पता लगाने का मुद्दा थिएरी टेम्पलियर के चयनित उत्तर में दूसरे उदाहरण में मौजूद है? <li *ngFor="let number of [0,1,2,3,4]">{{number}}</li>
जेकेरनी

इस समस्या के लिए यह सबसे अच्छा समाधान है
khush

1
@ Tobias81, मैंने यह सुनिश्चित करने के लिए जाँच की है कि परिवर्तन का पता लगाने के लिए बार-बार ngFor की सामग्री को फिर से बनाना नहीं है, एक घटक के निर्माता के अंदर एक प्रिंट स्टेटमेंट डालकर जिसे मैं उदाहरण ngFor निर्देश के एक बच्चे के रूप में बनाता हूं। मुझे नहीं लगता कि घटकों को हर परिवर्तन डिटेक्शन पुनरावृत्ति पर फिर से बनाया जा रहा है, इसलिए मुझे नहीं लगता कि वास्तव में एक समस्या है (कम से कम कोणीय 8 में)।
जेकेरनी

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
आप Thierrys के उत्तर में दिखाए गए Array.fill()की res.push()तरह सरणी उत्पन्न करने के लिए विधि का उपयोग भी कर सकते हैं ।
गुंटर ज़ोचबॉयर

हाँ, मैं कर सकता हूँ, लेकिन क्या कुछ गड़बड़ है push? मेरा मतलब है कि दोनों विधियाँ सही हैं लेकिन फिर भी यदि कोई भिन्नता है। उनके बीच।
परदीप जैन

3
नहीं, अभी भी एक अच्छा समाधान +1। मैं सिर्फ Array.fill()पुश का उपयोग करके लूप की तुलना में अधिक सुरुचिपूर्ण पाता हूं और यह संभवतः अधिक कुशल भी है।
गुंटर ज़ोचबॉयर

1
मुझे यह समाधान counter = Arrayबहुत पसंद है ;)
वैरी

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


मैं मानता हूं कि एरो एप्रोच बदसूरत है, लेकिन यह मेरे लिए समयपूर्व अनुकूलन जैसा लगता है।
अलुआन हदाद

3
बेशक, लेकिन यह भी एक निर्देश लिखने में एक व्यायाम। दूसरी ओर यह पाइप की तुलना में अधिक लंबा नहीं है, जो कि दूसरे लेन का दृष्टिकोण होगा।
pdudits

यह एक अच्छा बिंदु है, कस्टम संरचनात्मक निर्देशों की अवधारणा के साथ आपके कुछ प्राप्त करने के लिए बहुत सारे अवसर नहीं हैं।
अलुआन हद्दाद

: - अच्छा एक @pdudits फिर भी नवीनतम संस्करण के साथ काम करता plnkr.co/edit/8wJtkpzre3cBNokHcDL7?p=preview [अपने plnkr अद्यतन करने के लिए स्वतंत्र लग रहा है]
एटी

5

मैंने इसे Angular 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);
}

त्रुटि की जाँच करना और संक्षिप्तता उद्देश्य के लिए छोड़ दिया गया (जैसे कि यदि कदम नकारात्मक है तो क्या होता है)।


2
क्या html में कोई तरीके <div *ngfor="let i of 4, i++"></div>हो सकते हैं
निथिला शंमुगांथन

5

आप भी इस तरह का उपयोग कर सकते हैं

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

एचटीएमएल

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

4

आप लिटाश का उपयोग कर सकते हैं:

@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>हो सकते हैं
निथिला शंमुगांथन

यदि आपको iकिसी कोड की आवश्यकता या अनुक्रमणिका है तो आप कर सकते हैं*ngFor="let i of range; let i = index"
एलेक्स पो


2

चूंकि भरण () विधि (स्वीकृत उत्तर में उल्लिखित) बिना तर्क के एक त्रुटि फेंकती है, मैं कुछ इस तरह से सुझाव दूंगा (मेरे लिए काम करता है, कोणीय 7.0.4, टाइपस्क्रिप्ट 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>

यह मायकोलिलेशन में समय की मात्रा के लिए दोहराने का एक अच्छा और त्वरित तरीका है।

इसलिए यदि मेरा चयन 5 था, तो हैलो वर्ल्ड को 5 बार दोहराया जाएगा।


1

सूचकांक के साथ कस्टम संरचनात्मक निर्देश का उपयोग करना:

कोणीय दस्तावेज के अनुसार:

createEmbeddedView एक एम्बेडेड दृश्य Instantiates और इस कंटेनर में सम्मिलित करता है।

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.

जब angular 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 के साथ सरणी के माध्यम से Iterate:

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

क्या html में कोई तरीके <div *ngfor="let i of 4, i++"></div>हो सकते हैं
निथिला शंमुगांथन

आपको एक सरणी पर चलना होगा। यदि आपको स्केलर की आवश्यकता है, तो आप सही आकार के साथ एक सरणी पर पुनरावृत्ति कर सकते हैं और इसके अलावा एक स्केलर को तुरंत बदल सकते हैं: * ngFor = "सरणी का आइटम दें; i = इंडेक्स"
जनवरी क्लेमेंस स्टॉफ़रेगन

0

एक सरल तरीका है जो मैंने कोशिश की है

आप अपने घटक फ़ाइल में एक सरणी भी बना सकते हैं और आप इसे एक सरणी के रूप में लौटाकर * 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>

2
क्या html में कोई भी तरीके <div *ngfor="let i of 4, i++"></div>हो सकते हैं
निथिला शनमुगंथान

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>

यह हर पाने पर एक नया ऐरे बनाता है। ओवरहेड बना सकता है
रेमको विलेरमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.