【问题标题】:Angular4: How do I *ngFor, for every number in an int?Angular4:我如何 *ngFor,对于 int 中的每个数字?
【发布时间】:2017-11-14 23:18:21
【问题描述】:

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

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

【问题讨论】:

标签: html angular typescript angular2-ngfor


【解决方案1】:

我解决了这个问题:

在 TS 中:

months = [...Array(12).keys()];

在模板中:

<p *ngFor="let month of months">{{month+1}}</p>

【讨论】:

    【解决方案2】:

    根据 Angular 文档:

    createEmbeddedView() 实例化一个嵌入式视图并将其插入到此容器中。它接受一个上下文对象作为第二个参数: abstract createEmbeddedView(templateRef: TemplateRef, context?: C, index?: number): EmbeddedViewRef.

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

    使用上下文可选参数,你可以在组件中使用它 就像使用 *ngFor 一样在模板中提取它。

    app.component.html:

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

    import { Directive, Input, TemplateRef, ViewContainerRef, EventEmitter } from '@angular/core';
    
    @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,
            {
              index: i,
              odd: i % 2 == 1,
              even: i % 2 == 0,
              first: i == 0,
              last: i == num,
              length: num - 1,
            }
          );
      }
    }
    

    【讨论】:

      【解决方案3】:

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

      您可以创建另一个名为 countObservable 的变量

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

      在 HTML 中使用异步

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

      更新

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

      使用上面的countObservable代码代替

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

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

      this.count$.next(newNum);
      

      【讨论】:

      • 有趣的是,我想实现一个演示应用程序的功能,我试图展示一点点 Rxjs 知识。这是我最喜欢的解决方案;谢谢!
      • 这在我之后更改计数值时不起作用。有什么想法吗?
      • 您需要拦截变量的设置事件并重新生成可观察对象
      【解决方案4】:

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

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

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

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

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

      【讨论】:

      • 这是最适合 Angular 哲学的解决方案:它是可重复使用的(不像 Observable 解决方案,它必须在您想要另一个计数器的任何地方复制)。您的指令是否还使用&lt;span *forNumber="count"&gt;...&lt;/span&gt; 作为ng-template 的快捷方式?我认为应该可以做到这一点,但您可能需要更改一些内容。
      • 是的,可重用性是我想将其封装在指令中的原因。我还没有尝试将它与 * 运算符一起使用,并且很可能需要添加一些东西来进行更改检测。目前我将它与一组不可变的值一起使用,我急于使该功能正常工作,所以我没有注意所有细节
      • @Duncan 你现在可以在github.com/ngx-extensions/ngx-extensions 下找到这个和其他可重用元素:)
      【解决方案5】:

      您可以使用 管道过滤器轻松做到,它根据过滤器参数 = number 将空数组转换为多个子项。

      管道过滤器

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

      查看

      <div *ngFor="let n of [] | range:100"></div>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-06
        • 2018-02-09
        • 2019-01-27
        • 2019-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多