Angular 使用基于数字的ngFor多次重复HTML元素

Angular 使用基于数字的ngFor多次重复HTML元素,angular,Angular,如何使用*ngFor多次重复HTML元素 例如: 如果我将一个成员变量赋值为20。如何使用*ngFor指令使div重复20次?您可以使用以下命令: @Component({ (...) template: ` <div *ngFor="let i of Arr(num).fill(1)"></div> ` }) export class SomeComponent { Arr = Array; //Array type captured in a

如何使用
*ngFor
多次重复HTML元素

例如:
如果我将一个成员变量赋值为20。如何使用*ngFor指令使div重复20次?

您可以使用以下命令:

@Component({
  (...)
  template: `
    <div *ngFor="let i of Arr(num).fill(1)"></div>
  `
})
export class SomeComponent {
  Arr = Array; //Array type captured in a variable
  num:number = 20;
}
@组件({
(...)
模板:`
`
})
导出类组件{
Arr=Array;//变量中捕获的数组类型
数值:数值=20;
}
或实现自定义管道:

import {PipeTransform, Pipe} from '@angular/core';

@Pipe({
  name: 'fill'
})
export class FillPipe implements PipeTransform {
  transform(value) {
    return (new Array(value)).fill(1);
  }
}

@Component({
  (...)
  template: `
    <div *ngFor="let i of num | fill"></div>
  `,
  pipes: [ FillPipe ]
})
export class SomeComponent {
  arr:Array;
  num:number = 20;
}
从'@angular/core'导入{PipeTransform,Pipe};
@烟斗({
名称:“填充”
})
导出类FillPipe实现PipeTransform{
转换(值){
返回(新数组(值)).fill(1);
}
}
@组成部分({
(...)
模板:`
`,
管道:[填充管道]
})
导出类组件{
arr:数组;
数值:数值=20;
}

您可以在HTML中简单地执行此操作:

*ngFor="let number of [0,1,2,3,4,5...,18,19]"
并使用变量“number”进行索引。

更简单的方法:

定义一个helperArray,并根据要创建HTML元素的计数长度动态(或静态)实例化它。例如,我希望从服务器获取一些数据,并使用返回的数组长度创建元素

export class AppComponent {
  helperArray: Array<any>;

  constructor(private ss: StatusService) {
  }

  ngOnInit(): void {
    this.ss.getStatusData().subscribe((status: Status[]) => {
      this.helperArray = new Array(status.length);
    });
  }
}
导出类AppComponent{
helperArray:数组;
构造函数(私有ss:StatusService){
}
ngOnInit():void{
this.ss.getStatusData().subscribe((状态:status[])=>{
this.helperArray=新数组(status.length);
});
}
}
然后在我的HTML模板中使用helperArray

<div class="content-container" *ngFor="let i of helperArray">
  <general-information></general-information>
  <textfields></textfields>
</div>

使用
阵列的推荐解决方案存在两个问题:

  • 这是浪费。特别是对于大量的人
  • 你必须在某个地方定义它们,这样一个简单而普通的操作会导致很多混乱
  • 定义一个
    管道(一次),返回一个
    Iterable
    ,似乎更有效:

    import {PipeTransform, Pipe} from '@angular/core';
    
    @Pipe({name: 'times'})
    export class TimesPipe implements PipeTransform {
      transform(value: number): any {
        const iterable = <Iterable<any>> {};
        iterable[Symbol.iterator] = function* () {
          let n = 0;
          while (n < value) {
            yield ++n;
          }
        };
        return iterable;
      }
    }
    
    从'@angular/core'导入{PipeTransform,Pipe};
    @管道({name:'times'})
    导出类TimesPipe实现PipeTransform{
    变换(值:数字):任意{
    常量={};
    iterable[Symbol.iterator]=函数*(){
    设n=0;
    while(n<值){
    产量+n;
    }
    };
    返回可编辑;
    }
    }
    
    用法示例(使用动态宽度/高度渲染栅格):

    
    {{x}
    {{y}
    
    一个更简单、可重用的解决方案可能是使用这样的自定义结构指令

    import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
    
    @Directive({
      selector: '[appTimes]'
    })
    export class AppTimesDirective {
    
      constructor(
        private templateRef: TemplateRef<any>,
        private viewContainer: ViewContainerRef) { }
    
      @Input() set appTimes(times: number) {
        for (let i = 0 ; i < times ; i++) {
          this.viewContainer.createEmbeddedView(this.templateRef);
        }
      }
    
    }
    
    import{Directive,Input,TemplateRef,ViewContainerRef}来自“@angular/core”;
    @指示({
    选择器:“[appTimes]”
    })
    导出类apptimes指令{
    建造师(
    私有templateRef:templateRef,
    私有viewContainer:ViewContainerRef{}
    @Input()设置应用时间(时间:数字){
    for(设i=0;i
    然后像这样使用它:

    <span *appTimes="3" class="fa fa-star"></span>
    
    
    
    
    

    20
    替换为变量

    以下是Ilyass Lamrani结构指令的一个稍微改进的版本,允许您在模板中使用索引:

    @Directive({
      selector: '[appRepeatOf]'
    })
    export class RepeatDirective {
    
      constructor(private templateRef: TemplateRef<any>,
                  private viewContainer: ViewContainerRef) {
      }
    
      @Input()
      set appRepeatOf(times: number) {
        const initialLength = this.viewContainer.length;
        const diff = times - initialLength;
    
        if (diff > 0) {
          for (let i = initialLength; i < initialLength + diff; i++) {
            this.viewContainer.createEmbeddedView(this.templateRef, {
              $implicit: i
            });
          }
        } else {
          for (let i = initialLength - 1; i >= initialLength + diff ; i--) {
          this.viewContainer.remove(i);
        }
      }
    
    }
    
    @指令({
    选择器:“[appRepeatOf]”
    })
    导出类重复指令{
    构造函数(私有templateRef:templateRef,
    私有viewContainer:ViewContainerRef){
    }
    @输入()
    设置appRepeatOf(次数:个){
    const initialLength=this.viewContainer.length;
    const diff=乘以初始长度;
    如果(差异>0){
    for(设i=initialLength;i=initialLength+diff;i--){
    此.viewContainer.remove(i);
    }
    }
    }
    
    用法:

    <li *appRepeat="let i of myNumberProperty">
        Index: {{i}}
    </li>
    
    
    索引:{{i}
    
    
    如果您正在使用,可以执行以下操作:

    @Component({
      (...)
      template: `
        <div *ngFor="let i of Arr(num).fill(1)"></div>
      `
    })
    export class SomeComponent {
      Arr = Array; //Array type captured in a variable
      num:number = 20;
    }
    
    导入到组件中

    import * as _ from "lodash";
    
    *ngFor="let number of lodash.range(20)"
    
    在组件中声明成员变量以引用Lodash

    lodash = _;
    
    然后在您的视图中,您可以使用.20来替换组件中的任何变量

    import * as _ from "lodash";
    
    *ngFor="let number of lodash.range(20)"
    

    必须指出的是,绑定到视图中的函数可能代价高昂,这取决于您调用的函数的复杂性,因为更改检测将重复调用该函数。

    实现这一点的最有效和简洁的方法是添加迭代器实用程序。不要费心生成值。不要费心在视图中设置变量ngFor指令:

    function times(max: number) {
      return {
        [Symbol.iterator]: function* () {
          for (let i = 0; i < max; i++, yield) {
          }
        }
      };
    }
    
    @Component({
      template: ```
    <ng-template ngFor [ngForOf]="times(6)">
      repeats 6 times!
    </ng-template>
    
    ```
    })
    export class MyComponent {
      times = times;
    }
    
    <div *appRepeat="15">
      Testing
    </div>
    
    功能时间(最大:个){
    返回{
    [符号.迭代器]:函数*(){
    for(设i=0;i
    您不需要像大多数答案中建议的那样填充数组。如果在
    ngFor
    循环中使用索引,则只需创建一个长度正确的空数组:

    <li *ngFor="let element in elements; let i = index">
      <span>{{ i }}</span>
    </li>
    
    在你看来:

    import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
    
    @Directive({ selector: '[appRepeat]' })
    export class RepeatDirective {
      constructor(private templateRef: TemplateRef<any>, private viewContainerRef: ViewContainerRef) {
      }
    
      @Input() set appRepeat(loops: number) {
        for (let index = 0; index < loops; ++index) {
          this.viewContainerRef.createEmbeddedView(this.templateRef);
        }
      }
    }
    
    
    {{i}
    
    
    我知道您明确要求使用*ngFor进行此操作,但我想分享我使用结构化指令解决此问题的方法:

    function times(max: number) {
      return {
        [Symbol.iterator]: function* () {
          for (let i = 0; i < max; i++, yield) {
          }
        }
      };
    }
    
    @Component({
      template: ```
    <ng-template ngFor [ngForOf]="times(6)">
      repeats 6 times!
    </ng-template>
    
    ```
    })
    export class MyComponent {
      times = times;
    }
    
    <div *appRepeat="15">
      Testing
    </div>
    
    import{Directive,Input,TemplateRef,ViewContainerRef}来自“@angular/core”;
    @指令({选择器:'[appRepeat]'})
    导出类重复指令{
    构造函数(私有templateRef:templateRef,私有viewContainerRef:viewContainerRef){
    }
    @Input()设置appRepeat(循环:编号){
    for(让索引=0;索引
    这样,您就可以像这样使用它:

    <div *ngFor="let i of Count">
    
    
    测试
    
    您可以简单地使用它:

    HTML

    export class Component implements OnInit {
      Count = [];
    
      constructor() {
        this.Count.length = 10; //you can give any number
      }
    
      ngOnInit(): void {}
    }
    

    FillPipe类必须实现PipeTransform是的,你是对的!它更好;-)谢谢你指出这个ou