Angular2动态输入字段在输入更改时失去焦点
Posted
技术标签:
【中文标题】Angular2动态输入字段在输入更改时失去焦点【英文标题】:Angular2 Dynamic input field lose focus when input changes 【发布时间】:2017-07-08 10:59:05 【问题描述】:我正在制作一个动态表格。 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>
只要我在一个值的输入中写入一些文本,输入就会失去焦点。 如果我向一个字段添加许多值,并且我在一个值输入中写入一个字符,则输入失去焦点并且该字符被写入每个输入中。
【问题讨论】:
how to use track by inside ngFor angular 2的可能重复 【参考方案1】:当数组是原始类型时会发生这种情况,在您的情况下是 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;
这是link 关于同一问题,除了问题是针对 AngularJS 的,但问题与您的问题相对应。该页面最重要的摘录:
您正在重复一个数组并且您正在更改数组的项目(请注意,您的项目是字符串,它们是 JS 中的基元,因此“按值”进行比较)。由于检测到新项目,因此从 DOM 中删除旧元素并创建新元素(显然没有获得焦点)。
使用TrackBy
Angular 可以根据唯一标识符跟踪已添加(或删除)的项目,并仅创建或销毁已更改的内容,这意味着您不会失去对输入字段的关注:)
如链接中所示,您还可以修改您的数组以包含唯一的对象并使用 [(ngModel)]="value.id"
例如,但这可能不是您需要的。
【讨论】:
在我的例子中,我不是在迭代一个基元数组,而是一个对象数组(实际上是一个 FormArray),我仍然遇到同样的问题。即便如此,我还是按照@AJT_82 的建议解决了问题 @AlexisJoséBravoLlovera 很高兴听到它有效并且对您有所帮助! formarray 似乎发生了某种事情,我自己也不知道原因,因为我们确实在处理对象,类似的问题:***.com/questions/44445676/… 你先生是个英雄。谢谢。 @AJT82 非常感谢!这对我帮助很大,我一直在努力奋斗【参考方案2】:当我使用辅助函数迭代对象的键和值时,这发生在我身上:
<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
可能需要更改,则需要手动更新,以便更改检测器触发重新渲染。
【讨论】:
【参考方案3】:当您输入一些文本时,角度 ngOnChange 侦听器将运行,因此 ngFor 索引将重新呈现并且焦点将丢失。为了避免这个问题,可以将 trackFn 添加到 ngFor。有关该主题的更多详细信息,请参阅https://angular.io/api/core/TrackByFunction。在您的问题的代码解决方案下方:
在您的 html 代码中定义 ngFor 一个 trackFn 函数,该函数将对应于 .ts 文件中声明的 trackByFn 函数。
<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函数:
trackByFn(i: number, items: any)
return index //returning the index itself for avoiding ngFor to change focus after ngModelChange
【讨论】:
以上是关于Angular2动态输入字段在输入更改时失去焦点的主要内容,如果未能解决你的问题,请参考以下文章
当项目更改时,CoreData 绑定的 NSTableView 会失去输入焦点,但前提是已排序