Повторите элемент HTML несколько раз с помощью ngFor на основе числа



Как использовать *ngFor чтобы повторить HTML-элемент несколько раз?



например:
Если у меня есть переменная-член, назначенный 20. Как я могу использовать директиву * ngFor, чтобы повторить div 20 раз?

699   8  

8 ответов:

вы можете использовать следующее:

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

есть две проблемы с рекомендуемыми решениями с помощью Arrays:

  1. это расточительно. В частности, для больших количеств.
  2. вы должны определить их где-то, что приводит к большому беспорядку для такой простой и распространенной операции.

кажется более эффективным определить Pipe (один раз), возвращается Iterable:

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

@Pipe({name: 'times'})
export class TimesPipe implements PipeTransform {
  transform(value: number): any {
    const iterable = {};
    iterable[Symbol.iterator] = function* () {
      let n = 0;
      while (n < value) {
        yield ++n;
      }
    };
    return iterable;
  }
}

пример использования (рендеринг сетки с динамической шириной / высотой):

<table>
    <thead>
      <tr>
        <th *ngFor="let x of colCount|times">{{ x }}</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let y of rowCount|times">
        <th scope="row">{{ y }}</th>
        <td *ngFor="let x of colCount|times">
            <input type="checkbox" checked>
        </td>
      </tr>
    </tbody>
</table>
<div *ngFor="let dummy of ' '.repeat(20).split(''), let x = index">

заменить 20 переменной

вы можете просто сделать это в HTML:

*ngFor="let number of [0,1,2,3,4,5...,18,19]"

и использовать переменную "число" для индексирования.

более простое и многоразовое решение, возможно, использовать пользовательскую структурную директиву, как это.

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

}

и использовать его так:

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

простой подход:

определите 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);
    });
  }
}

затем используйте helperArray в моем шаблоне HTML.

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

вот немного улучшенная версия структурной директивы Ильяса Ламрани, которая позволяет использовать индекс в вашем шаблоне:

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

}

использование:

<li *appRepeat="let i of myNumberProperty">
    Index: {{i}}
</li>

Если вы используете Лодашь, вы можете сделать следующее:

импорт Лодашь в компоненте.

import * as _ from "lodash";

объявите переменную-член в компоненте для ссылки на Lodash.

lodash = _;

тогда, на ваш взгляд, вы можете использовать функции. 20 может быть заменен любой переменной в вашем компоненте.

*ngFor="let number of lodash.range(20)"

следует сказать, что привязка к функциям в представлении может быть дорогостоящей, в зависимости о сложности функции, которую вы вызываете, поскольку обнаружение изменений будет вызывать функцию повторно.

Comments

    Ничего не найдено.