【问题标题】:Why some data are not displayed after editing source used by ngFor?为什么编辑ngFor使用的源后有些数据不显示?
【发布时间】:2019-08-26 21:55:55
【问题描述】:

我现在正在使用 Angular 6。

所以我有一个我想通过 ngFor 显示的对象数组。 从 html 页面,我可以执行 2 种不同的操作 - 向该数组添加一个新项目并从那里删除一个项目。

会发生的情况是,有时添加新项目会导致现有项目从视图表示中消失。

更确切地说,当这种情况发生时,我有一个场景(它也在所附的屏幕截图中描述):

  1. 添加几个项目,所以我在一个数组中总共有 5 个项目,显示值为 "a","b","c","d",null
  2. 删除项目“c”,然后删除项目“b”(所以现在我有“a”,“d”,null)
  3. 设置最后一项的值(现在我有 "a","b","e")
  4. 添加新项目。这是一个问题开始的地方。项目已添加到数组中,但同时值“d”在此之后不再显示。现在奇怪的是值“d”实际上仍在模型中(屏幕截图上的最后一个日志),但它只是没有显示。

说实话,甚至不知道如何开始调试。

添加新商品代码:

  addItem () {
    var newItem = new CardItem(String(++this.itemCount), null);
    console.log("Created new item: "+JSON.stringify(newItem));

    this.testCard.back.push(newItem);
    console.log("Items after adding new option: "+JSON.stringify(this.testCard.back));
  }

删除项目代码:

  removeAnswer (itemIndex: string) { 
    if (itemIndex!=null) {
      var index = this.testCard.back.findIndex(answ => answ.id == itemIndex);
      console.log("Index of item to be removed: ["+index+"]. Object to be removed: ["+JSON.stringify(this.testCard.back[index])+"]");

      this.testCard.back.splice(index,1);
      console.log("Item after removal: "+JSON.stringify(this.testCard.back));
    } else {
      console.debug("Can't remove item, index is missed. ["+itemIndex+"].");
    }
  }
    <mat-form-field *ngFor="let cardBack of testCard.back; let i = index; let first = first; let last = last">
      <input matInput placeholder="Item {{i+1}}" name="item{{i+1}}" [(ngModel)]="cardBack.item" >
      <mat-icon matSuffix (click)="removeItem(cardBack.id)">close</mat-icon>
    </mat-form-field>

提前谢谢大家!

已添加

我通过将trackBy 添加到我的 NgFor(作为答案添加)来解决了一个问题。但是,我不明白为什么它在一种情况下有效,但在另一种情况下无效。

所以我尝试实现 trackBy 函数。一个有效的只是返回传递给函数的索引值。不起作用的实现是使用唯一的back.id 值,但它并没有以某种方式起作用。我认为对于 trackBy 函数,我们需要一些不会改变的对象的唯一标识符,所以这就是我尝试使用 back.id 的原因——它生成一次,之后就不会改变。 另一方面,在我们从 NgFor 中添加/删除项目之后,$index 的值每次都会改变,因此相同的项目将被不同的 id 跟踪(仍然是唯一的)。

所以在这两种情况下,函数都会返回唯一值。为什么在 trackBy 函数中使用 $index 时它可以工作,但当我尝试使用作为对象一部分的唯一标识符 (back.id) 时它不起作用?

【问题讨论】:

  • 我根据您的代码创建了一个 stackblitz,它运行良好。 angular-jwwfnh.stackblitz.io。由于您的共享代码和模板中的方法名称不匹配,因此进行了一些更正。
  • 你把默认的ChangeDetectionStrategy改成onPush了吗?
  • @Batajus,不,我没有覆盖它。
  • @ashish.gd,我相信您在项目中使用了 Angular 7。正如我所提到的,我正在使用 Angular 6。我会尝试更新到 Angular 7,并会在此处回复答案。
  • @ashish.gd 我用 Angular 7 尝试过,但令人惊讶的是它对我也不起作用。修复它的方法是添加 trackBy 函数,该函数按索引跟踪元素。在修复它之前,我注意到一件奇怪的事情。即使“项目 2”的输入值消失了,它仍然在名为 ng-reflect-model 的元素属性中正确显示,据我所知,这是出于调试目的,应该显示一个必须由 ngModel 使用的值。跨度>

标签: angular ngfor


【解决方案1】:

通过将trackBy 函数添加到按索引跟踪项目的ngFor 来解决此问题。 所以基本上我替换了下一个代码:

<mat-form-field *ngFor="let cardBack of testCard.back; let i = index; let first = first; let last = last">

与:

<mat-form-field *ngFor="let cardBack of testCard.back; let i = index; trackBy: trackBackBy">

函数 trackBackBy 如下所示:

trackBackBy (index, back) {
    return index;
}

对于为什么添加新元素会使第二个元素的值消失(属性ng-reflect-model 的值实际上一直都是正确的),但没有答案。至少在这里寻找任何帮助将不胜感激。

我也尝试在trackBackBy 函数中使用back.id,但它没有以某种方式工作。我认为对于trackBy 函数,我们需要一些不会改变的对象标识符,这就是我尝试使用back.id 的原因——它只生成一次,之后就不会改变。 另一方面,在我们从NgFor 添加/删除项目之后,$index 的值每次都会改变,因此相同的项目将被不同的 id 跟踪(仍然是唯一的)。

所以在这两种情况下,函数都会返回唯一值。为什么在 trackBy 函数中使用 $index 时它可以工作,但当我尝试使用作为对象一部分的唯一标识符 (back.id) 时它不起作用?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-18
    • 2017-01-06
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多