关于html:Angular4:如何为int中的每个数字* ngFor?

Angular4: How do I *ngFor, for every number in an int?

我的组件中有一个名为" count"的int属性。

我想显示一个p标签X次,其中X是我的count属性等于的int。除了弄乱假数组,真的没有简单的方法可以做到这一点吗?


您可以使用管道过滤器轻松完成此操作,该过滤器根据过滤器参数= number将空数组转换为多个子级。

管道过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Pipe, PipeTransform } from '@angular/core';  

@Pipe({  
    name: 'range',  
    pure: false  
})  

export class RangePipe implements PipeTransform {  
    transform(items: any[], quantity: number): any {  
      items.length = 0;
      for (let i = 0; i < quantity; i++) {
        items.push(i);
      }
      return items;
    }  
}

看法

1
 

Plnkr:https://plnkr.co/edit/Yn775KSbBeUPeyaI9sep?p=preview

您可以创建另一个名为countObservable

的变量。

1
  countObservable = Observable.range(0, this.count).toArray();

在HTML中将异步用于

1
  <p *ngFor="let num of countObservable | async">Hello {{num}}

更新

如果需要更新号码,可以使用flatMap

代替上面的countObservable代码,使用此

1
2
3
count$= new BehaviorSubject(10);
countObservable$ =
  this.count$.flatMap(count => Observable.range(0, count).toArray()) ;

要更改数字值,只需更新count$

1
this.count$.next(newNum);


我有点不喜欢每次要渲染元素n次时都创建一个大小为n的空数组的方法,所以我创建了一个自定义的结构指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { Directive, Input, TemplateRef, ViewContainerRef, isDevMode, EmbeddedViewRef } from '@angular/core';

export class ForNumberContext {
  constructor(public count: number, public index: number) { }
  get first(): boolean { return this.index === 0; }

  get last(): boolean { return this.index === this.count - 1; }

  get even(): boolean { return this.index % 2 === 0; }

  get odd(): boolean { return !this.even; }
}

@Directive({
  selector: '[ForNumber]'
})
export class ForNumberDirective {


 @Input() set forNumberOf(n: number) {
    this._forNumberOf = n;
    this.generate();
  }

  private _forNumberOf: number;

  constructor(private _template: TemplateRef<ForNumberContext>,
    private _viewContainer: ViewContainerRef) { }

  @Input()
  set ngForTemplate(value: TemplateRef<ForNumberContext>) {
    if (value) {
      this._template = value;
    }
  }

  private generate() {
    for (let i = 0; i < this._forNumberOf; i++) {
      this._viewContainer.createEmbeddedView(this._template, new ForNumberContext(this._forNumberOf, i));
    }
  }

}

然后您可以按以下方式使用它:

1
2
<ng-template ForNumber [forNumberOf]="count" let-index="index">
<span>Iteration: {{index}}!</span></ng-template>

请注意,我还没有对其进行广泛的测试,所以我不能保证它的防弹性能:)


根据Angular文档:

createEmbeddedView() Instantiates an embedded view and inserts it into this container. it accepts a context object as second parameter:
abstract createEmbeddedView(templateRef: TemplateRef, context?: C, index?: number): EmbeddedViewRef.

当angular通过调用createEmbeddedView创建模板时,它也可以传递将在ng-template内部使用的上下文。

使用上下文可选参数,您可以在组件中使用它
就像使用* ngFor。

一样,将其提取到模板中。

app.component.html:

1
2
3
4
5
6
7
8
 <p *for="randomNumber; let i = index; let first = first; let last = last; let even = even, let odd = odd; length = length">
   index :{{i}},
   length:{{length}},
   is first : {{first}},
   is last : {{last}},
   is even : {{even}},
   is odd : {{odd}}
 </p>

for.directive.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { Directive, Input, TemplateRef, ViewContainerRef, EventEmitter } from '@angular/core';

@Directive({
  selector: '[for]'
})
export class ForDirective {

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

  @Input('for') set loop(num: number) {
    for (var i = 0; i < num; i++)
      this.viewContainer.createEmbeddedView(
        this.templateRef,
        {
          index: i,
          odd: i % 2 == 1,
          even: i % 2 == 0,
          first: i == 0,
          last: i == num,
          length: num - 1,
        }
      );
  }
}