簡體   English   中英

Angular2 動態輸入字段在輸入更改時失去焦點

[英]Angular2 Dynamic input field lose focus when input changes

我正在制作一個動態表格。 一個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>

一旦我在一個值的輸入中寫入一些文本,輸入就會失去焦點。 如果我向一個字段添加許多值,並且我在輸入的值中寫入一個字符,則輸入會失去焦點並且該字符會寫入每個輸入中。

當數組是原始類型時會發生這種情況,在您的情況下是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"例如,但這可能不是您需要的。

當我使用輔助函數迭代對象的鍵和值時,這發生在我身上:

<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可能需要變化的情況下,它需要手動更新,以便更改檢測器將觸發重新渲染。

當您輸入一些文本時,angular 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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM