在 ngIf 中使用 array.prototype.some

Using array.prototype.some inside ngIf

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

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

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

Parser Error: Bindings cannot contain assignments at column 34 in [questionniare.factors.some(item => item.intensities.length > 0)]

但是如你所见,我的情况下没有任何作业。那么问题是什么,我该如何解决?

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

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

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

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

更好的解决方案是在数组发生变化时更新组件上的值

你可以这样做:

@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 来完成它,但这应该是最有效的方法

错误消息提到 "assignment" 但问题是您正在组件模板内创建箭头函数,这是不允许的。 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 is similar to your original code and gives the same error. This other stackblitz 显示了组件代码中定义的回调函数的相同示例。


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

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

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