输入更改时 Angular2 动态输入字段失去焦点

新手上路,请多包涵

我正在制作动态表格。 A Field 有一个值列表。每个值都由一个字符串表示。

 export class Field{
    name: string;
    values: string[] = [];
    fieldType: string;
    constructor(fieldType: string) {this.fieldType = fieldType;}
}

我的组件中有一个函数可以为该字段添加一个新值。

 addValue(field){
    field.values.push("");
}

值和按钮在我的 HTML 中显示如下。

 <div id="dropdown-values" *ngFor="let value of field.values; let j=index">
    <input type="text" class="form-control" [(ngModel)]="field.values[j]" [name]="'value' + j + '.' + i"/><br/>
</div>
<div class="text-center">
    <a href="javascript:void(0);" (click)="addValue(field)"><i class="fa fa-plus-circle" aria-hidden="true"></i></a>
</div>

一旦我在一个值的输入中写了一些文本,输入就会失去焦点。如果我向一个字段添加多个值并在其中一个值输入中写入一个字符,则该输入会失去焦点并且该字符会写入每个输入中。

原文由 Elbbard 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 261
2 个回答

当数组是原始类型时会发生这种情况,在您的例子中是 String 数组。这可以通过使用 TrackBy 来解决。因此,更改您的模板以匹配以下内容:

 <div *ngFor="let value of field.values; let i=index; trackBy:trackByFn">
    <input type="text" [(ngModel)]="field.values[i]"  /><br/>
</div>
<div>
    <button (click)="addValue(field)">Click</button>
</div>

并在 ts 文件中添加函数 trackByFn ,它返回值的(唯一) index

 trackByFn(index: any, item: any) {
   return index;
}

这是关于同一问题的 链接,除了问题是针对 AngularJS 的,但问题与您的问题相对应。该页面最重要的摘录:

您在一个数组上重复,并且您正在更改数组的项目(请注意,您的项目是字符串,它们是 JS 中的基元,因此“按值”进行比较)。由于检测到新项目,旧元素将从 DOM 中删除并创建新元素(这显然不会获得焦点)。

使用 TrackBy Angular 可以根据唯一标识符跟踪添加(或删除)了哪些项目,并仅创建或销毁更改的内容,这意味着您不会失去对输入字段的关注:)

如链接中所示,您还可以修改数组以包含唯一的对象并使用 [(ngModel)]="value.id" 例如,但这可能不是您需要的。

原文由 AT82 发布,翻译遵循 CC BY-SA 3.0 许可协议

当我使用辅助函数迭代对象的键和值时,这发生在我身上:

 <div *ngFor="let thing of getThings()" [attr.thingname]="thing.key">
  ... {{ applyThing(thing.value) }}
</div>

在我的组件中,我返回了一个包含键/值对的对象数组:

 export ThingComponent {
  ...

  //this.things = { a: { ... }, b: { ... }, c: { ... } }

  public getThings() {
    return Object.keys(this.things).map((key) => {
      return {key: key, value: this.things[key] }
    })
  }
}

@AJT_82 给出的答案绝对与宣传的完全一样。但是在我的例子中,具体问题是辅助函数 getThings() 每次都返回一个新的对象列表。即使它们的内容相同,对象本身也会在每次调用函数时重新生成(这发生在变更检测期间),因此,对于变更检测器而言,它们具有不同的身份,并且在每次模型更改时都会重新生成表单。

在我的例子中,简单的解决方案是缓存 getThings() 的结果并将其用作迭代器:

 <div *ngFor="let thing of cachedThings" [attr.thingname]="thing.key">
  ... {{ applyThing(thing.value) }}
</div>

 export ThingComponent {
  public cachedThings = getThings()
  ...

  //this.things = { a: { ... }, b: { ... }, c: { ... } }

  private getThings() {
    return Object.keys(this.things).map((key) => {
      return {key: key, value: this.things[key] }
    })
  }
}

cachedThings 可能需要改变的情况下,需要手动更新它,以便更改检测器将触发重新渲染。

原文由 t.888 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题