【问题标题】:Using array.prototype.some inside ngIf在 ngIf 中使用 array.prototype.some
【发布时间】:2019-10-18 18:55:57
【问题描述】:

我正在使用第 8 版开发 Angular 应用程序。在ngIf 表达式中,我想检查数组中存在的东西。所以我写了下面的表达式:

*ngIf="questionniare.factors.some(item => item.intensities.length > 0)"

但现在我在控制台窗口中收到此错误:

解析器错误:绑定不能包含第 34 列的赋值 [questionniare.factors.some(item => item.intensities.length > 0)]

但是如你所见,我的情况没有任何任务。那么问题出在哪里,我该如何解决呢?

(我知道我可以定义一个方法并在该方法内完成这项工作,但我想知道这是否是我下次应该考虑的对 ngIf 的限制?)

【问题讨论】:

  • 你总是可以使用管道来完成这些任务。看看这个-stackoverflow.com/questions/43117917/…
  • 赋值肯定是在隐藏的 for 循环中进行的,以遍历 de Array.prototye.some 函数中的数组

标签: arrays angular angular-ng-if any


【解决方案1】:

错误消息提到了“赋值”,但问题是您正在组件模板内创建箭头函数,这是不允许的。一个feature request 已经发布在 GitHub 上,请求支持在 Angular 模板中创建这些函数。

为了在模板中使用Array.prototype.some,您必须在组件代码中定义谓词:

// You can define the predicate as a method
public itemHasIntensities(item): boolean {
  return item => item.intensities.length > 0;
}

// You can also define the predicate as an arrow function
public itemHasIntensities = (item): boolean => item.intensities.length > 0;

并将该函数作为参数传递给模板中的Array.prototype.some

*ngIf="questionniare.factors.some(itemHasIntensities)"

This stackblitz 与您的原始代码相似,并给出相同的错误。 This other stackblitz 显示了与组件代码中定义的回调函数相同的示例。


话虽如此,正如问题中提到的,最简单的解决方案是在组件方法中评估整个条件:

public showElement(): boolean {
  return this.questionniare.factors.some(item => item.intensities.length > 0);
}
*ngIf="showElement()"

注意:建议记忆函数以避免性能问题。

【讨论】:

  • 感谢 ConnorsFan。您对模板内箭头功能使用的关注非常有帮助。您和@ElliotMendiola 的回答都足以被标记为已接受。
【解决方案2】:

问题在于您的绑定正在遍历列表并跟踪在后台分配的值。

对此有几个解决方案,首先是将您的逻辑放在执行此操作的组件类的公共方法中,这是两种解决方案中较慢的一种,因为每次更改检测运行时它都会检查您的数组值。

更好的解决方案是在数组更改时更新组件上的值

你可以这样做:

@Component({
  selector: 'my-component',
  templateUrl: 'my-component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyComponent {
  @Input()
  set questionaire(value: Questionaire) {
    this.questionaire$.next(value);
  }

  readonly questionaire$ = new ReplaySubject<Questionaire>(1);
  readonly hasIntensities$ = this.questionaire$.pipe(
    map(questionaire => questionniare.factors.some(item => item.intensities.length > 0))
  );
};

然后在模板中你可以做这样的事情: *ngIf="hasIntensities$ | async"

您也可以通过更改检测器 ref 和 ngOnChanges 来完成它,但这应该是最有效的方法

【讨论】:

  • 我不确定他问的是什么——他可以做很多事情来解决具体问题——问题是在 ngIf 指令中使用数组纯方法是否有限制跨度>
  • 他问So what's the problem and how can I fix it?他并没有具体说明他想要解决方案,而且我没有看到他问为什么他不能在任何地方使用 ngif 中的数组纯方法
  • 感谢@ElliotMendiola 和@YochaiAkoka,你们俩都是真的。我先问了So what's the problem and how can I fix it?,然后问了if this is a limitation on ngIf that I should consider next times?。因此,欢迎所有注释和解决方案。
【解决方案3】:

这不是在 Angular 文档中编写的,但看起来你不能在结构指令中使用 Array.some,你应该将此逻辑移动到组件内的特定函数中。

【讨论】:

  • 所以我认为我应该每次尝试功能以了解它们是否有效。这感觉很糟糕。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 2017-05-23
相关资源
最近更新 更多