如何在 ngFor 循环中创建变量?

Posted

技术标签:

【中文标题】如何在 ngFor 循环中创建变量?【英文标题】:How to create variable in ngFor loop? 【发布时间】:2016-05-17 09:30:28 【问题描述】:

我正在尝试找出如何在 ngFor loop 中创建变量。

我有一个这样的循环:

<td *ngFor="#prod of products">
  <a href="getBuild(branch,prod)?.url">
    getBuild(branch,prod)?.status
   </a>
</td>

您可以看到getBuild 调用必须重复多次。 (在我的实际示例中更多次)。我想要一种方法,在循环内一次在模板中创建这个变量并简单地重用它。

有没有办法做到这一点?

【问题讨论】:

基本同一个问题:***.com/questions/35162539/… 【参考方案1】:

尽管可以就简单地编写一个新的子组件的优点进行争论。我认为以下解决方案是对所提问题的最正确答案。

<div *ngFor="let person of listOfPeople">
  <ng-container
    *ngTemplateOutlet="introText; context:  title: getTitle(person), color: person.color "
  ></ng-container>
</div>

<ng-template #introText let-title="title" let-color="color">
  <p [style.color]="color">
    title loves the color color
  </p>
</ng-template>

查看codesandbox of this。 这将允许定义多个模板变量,并无限次重复使用计算的输出。

使用 ng-template 的原因:

正如 OP 所提到的,这比全新的组件更轻。因此,如果您有一个重用计算逻辑的简单模板,这可能是一个不错的选择 在 在某些情况下,模板需要在同一个文件中 - 我遇到了 例如,使用“mat-stepper”(材料库)组件

避免使用 ng-template 的原因:

如果代码应该在其他组件中可重用 如果模板变得过于复杂,它会变得更加混乱而不是有用

【讨论】:

【参考方案2】:

在 *ngIf 解决方案上的改进,您可以始终保持真实条件,不留下任何罪魁祸首

<ng-container *ngFor="let item of items">
    <ng-container *ngIf="getMyVariableValue(item.id) || true; let myVariable">
         content here 
    </ng-container>
</ng-container>

我要注意的一个观察结果是,当函数“getMyVariableValue”返回 nullundefined 时,它并没有像我那样来,而是它的值来了作为真实。我使用的是 Angular 11.2.3 版。

【讨论】:

【参考方案3】:

虽然不理想,但另一种方法可能是使用 *ngIf

<td *ngFor="#prod of products">
  <ng-container *ngIf="build:getBuild(branch,prod); let state">
    <a href="state.build?.url">
      state.build?.status
    </a>
  </ng-container>
</td>

由于 *ngIf 表达式返回一个对象,所以它总是 thruthy,所以 ng-container 中的内容总是会被渲染。结果对象被分配给状态变量,以后可以重用。 ng-container 不插入 dom 元素。

【讨论】:

这与另一个已经发布的答案基本相同。 ***.com/a/53558536/31532【参考方案4】:

使用 Angular 4,您可以这样做:

<td *ngFor="#prod of products">
  <div *ngIf="getBuild(branch,prod); let build">
    <a href="build.url">
     build.status
    </a>
  </div>
</td>

【讨论】:

【参考方案5】:

我认为局部变量(使用 # 字符定义)不适用于您的用例。

事实上,当您在 html 元素上定义局部变量时,它对应于组件(如果有)。当元素上没有组件时,变量引用元素本身。

为局部变量指定值允许您选择与当前元素关联的特定指令。例如:

<input #name="ngForm" ngControl="name" [(ngModel)]="company.name"/>

将在name 变量中设置与当前关联的ngForm 指令的实例。

因此,局部变量并不针对您想要的,即设置为循环的当前元素创建的值。

如果你尝试这样做:

<div *ngFor="#elt of eltList" >
  <span #localVariable="elt.title"></span>
  localVariable
</div>

您将遇到以下错误:

Error: Template parse errors:
There is no directive with "exportAs" set to "elt.title" ("
  <div *ngFor="#elt of eltList" >
    <span [ERROR ->]#localVariable="elt.title"></span>
    localVariable
  </div>
"): AppComponent@2:10

Angular2 实际上会在此处查找与提供的名称 elt.title 匹配的指令)...查看此 plunkr 以重现错误:https://plnkr.co/edit/qcMGr9FS7yQD8LbX18uY?p=preview

有关详细信息,请参阅此链接:http://victorsavkin.com/post/119943127151/angular-2-template-syntax,“局部变量”部分。

除了迭代的当前元素之外,ngFor 只提供了一组导出值,这些值可以别名为局部变量:indexlastevenodd

查看此链接:https://angular.io/docs/ts/latest/api/common/NgFor-directive.html

你可以做的是创建一个子组件来显示循环中的元素。它将接受当前元素作为参数并创建您的“局部变量”作为组件的属性。然后,您将能够在组件的模板中使用此属性,以便循环中的每个元素创建一次。这是一个示例:

@Component(
  selector: 'elt',
  template: `
    <div>attr</div>
  `
)
export class ElementComponent 
  @Input() element;

  constructor() 
    // Your old "localVariable"
    this.attr = createAttribute(element.title);
  

  createAttribute(_title:string) 
    // Do some processing
    return somethingFromTitle;
  

以及使用方法:

<div *ngFor="#elt of eltList" >
  <elt [element]="elt></elt>
</div>

【讨论】:

我认为你是对的。我希望有一个更简单的方法,但现在看起来不可能。恕我直言,如果有一种语法可以将本地变量设置为模板表达式的结果,那就太好了。它可以使这种类型的使用更容易一些。 是的,同意!我在 Angular github 上发布了一个问题,以了解是否有相关计划:github.com/angular/angular/issues/6947。 请务必注意 ngFor 上的细微变化:*ngFor="let myVar of list"。看看:(angular.io/docs/ts/latest/api/common/NgFor-directive.html)【参考方案6】:

我认为这是制作子组件的经典案例。

<td *ngFor="#prod of products">
    <subComp [prod]=prod></subComp>
</td>

然后您的组件将有一个prod 输入并在OnInit 中运行一次所需的函数。

简单的例子 plunk here

【讨论】:

我可以创建一个以分支和产品为输入的子组件。对于可以在“父”组件模板中完成的几行 HTML 来说,这似乎很重。我希望有某种方法可以在 ngFor 中分​​配一个变量并在循环体中使用它。【参考方案7】:

不,只需将每个branch/prod 组合的结果缓存在getBuild 中,或者只要使用与以前相同的值调用它即可。

【讨论】:

知道我可以缓存结果。问题不在于计算需要很长时间(它已经被缓存)。只是我不想在 for 循环的主体中多次重复调用。我希望有一种从概念上讲的方法:“build = getBuild(branch,prod)”,然后在循环内使用 build。 我很确定这是不可能的。如果计算成本不高,我也不会打扰。

以上是关于如何在 ngFor 循环中创建变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在视图中仅循环一次对象(单个 *ngFor)?

如何在使用 *ngFor 创建的 ionic 3 组件中为 css 类变量动态赋值

如何在 ngfor 中向元素添加 id 以及在 ngfor 中条件创建元素

如何在角度 2 中使用 ngFor 仅循环遍历数组到某些对象

*ngFor - 如果找到,如何在模板循环中覆盖值

如何在 1 个单个 div 中生成 *ngFor 循环项,而不是每个项目周围都有一个 div 容器