关注新添加的input元素

我有一个新的Angular 2应用程序与input框列表。 当用户点击返回键时,我在他们正在编辑的那个之后立即添加一个新的input框。 或者说,我(asynchronous)向模型中的数组添加一个新条目,这将导致Angular 2在不久的将来自动生成一个新的input框。

我怎样才能使input焦点自动改变到新添加的元素?

或者,我得到一个引起DOM生成的模型对象的引用。 从组件代码中,有没有一种方法来search代表特定模型对象的DOM元素?

这是我的代码,只是使这个工作。 希望这对于一些Angular 2开发者来说足够让人反感:-)

app.WordComponent = ng.core .Component({ selector: 'word-editor', template:'<input type="text" [value]="word.word" (input)="word.update($event.target.value)" (keydown)="keydown($event)"/>', styles:[ '' ], properties:[ 'list:list', 'word:word' ] }) .Class({ constructor:[ function() { } ], keydown:function(e) { if(e.which == 13) { var ul = e.target.parentNode.parentNode.parentNode; var childCount = ul.childNodes.length; this.list.addWord("").then(function(word) { var interval = setInterval(function() { if(childCount < ul.childNodes.length) { ul.lastChild.querySelector('input').focus(); clearInterval(interval); } }, 1); }); } } }); 

如果允许我这样做,我会参与@Sasxa答案,并修改它,使其更像你正在寻找的东西。

一些变化

  • 我将使用ngFor所以angular2添加新的input,而不是自己做。 主要目的是使angular2迭代它。
  • 而不是ViewChild我将使用ViewChildren返回一个具有changes属性的QueryList 。 这个属性是一个Observable,它在元素改变后返回元素。

由于在ES5中,我们没有装饰器,我们必须使用queries属性来使用ViewChildren

零件

 Component({ selector: 'cmp', template : ` <div> // We use a variable so we can query the items with it <input #input (keydown)="add($event)" *ngFor="#input of inputs"> </div> `, queries : { vc : new ng.core.ViewChildren('input') } }) 

关注最后一个元素。

 ngAfterViewInit: function() { this.vc.changes.subscribe(elements => { elements.last.nativeElement.focus(); }); } 

就像我之前说过的,ViewChildren返回一个包含changes属性的QueryList。 当我们每次订阅它时都会返回元素列表。 列表elements包含last属性(在其他情况下),在这种情况下,返回最后一个元素,我们使用nativeElement和最后focus()

添加input元素这是纯粹的方便,input数组没有真正的目的, ngFor

 add: function(key) { if(key.which == 13) { // See plnkr for "this.inputs" usage this.inputs.push(this.inputs.length+1); } } 

我们在数组上推一个虚拟物品,以便重绘。

使用ES5的示例: http : //plnkr.co/edit/DvtkfiTjmACVhn5tHGex

使用ES6 / TS的示例: http ://plnkr.co/edit/93TgbzfPCTxwvgQru2d0? p= preview

更新29/03/2016

时间已经过去,事情已经澄清,总是有最好的实践来学习/教导。 我通过改变一些事情简化了这个答案

  • 而不是使用@ViewChildren并订阅它,我做了一个指令,每当创build一个新的input时就会被安装
  • 我正在使用Renderer来使WebWorker安全。 原始答案直接访问nativeElement focus()是不鼓励的nativeElement
  • 现在我听keydown.enter ,它简化了按键事件,我不必检查which值。

重点。 该组件看起来像(下面的简单的完整的代码)

 @Component({ template: `<input (keydown.enter)="add()" *ngFor="#input of inputs">`, }) add() { this.inputs.push(this.inputs.length+1); } 

和指令

 @Directive({ selector : 'input' }) class MyInput { constructor(public renderer: Renderer, public elementRef: ElementRef) {} ngOnInit() { this.renderer.invokeElementMethod( this.elementRef.nativeElement, 'focus', []); } } 

正如你所看到的,我调用invokeElementMethod来触发元素的focus ,而不是直接访问元素。

这个版本比原版更清洁,更安全。

plnkrs更新至beta 12

使用ES5的示例: http : //plnkr.co/edit/EpoJvff8KtwXRnXZJ4Rr

使用ES6 / TS的示例: http : //plnkr.co/edit/em18uMUxD84Z3CK53RRe

看看ViewChild ,这里是一个例子 。 这可能是你正在寻找的东西:

 import {Component, ViewChild} from 'angular2/core' @Component({ selector: 'my-app', providers: [], template: ` <div> <input #name> </div> `, directives: [] }) export class App { @ViewChild('name') vc: ElementRef; ngAfterViewInit() { this.vc.nativeElement.focus(); } } 

您可以实现一个简单的input文本指令,以便每当创build一个新的input时,它将自动自动对焦。 在视图完全初始化之后, focus()方法在ngAfterViewInit()组件的生命周期钩子内被调用。

 @Directive({ selector: 'input[type=text]' }) export class FocusInput implements AfterViewInit { private firstTime: bool = true; constructor(public elem: ElementRef) { } ngAfterViewInit() { if (this.firstTime) { this.elem.nativeElement.focus(); this.firstTime = false; } } } 

在组件中使用FocusInput指令:

 @Component({ selector: 'app', directives: [FocusInput], template: `<input type="text" (keyup.enter)="last ? addNewWord():0" *ngFor="#word of words; #last = last" [value]="word.word" #txt (input)="word.word = txt.value" />{{words |json}}` }) export class AppComponent { words: Word[] = []; constructor() { this.addNewWord(); } addNewWord() { this.words.push(new Word()); } } 

请注意以下几点:

  1. (keyup.enter)事件用于检测何时按<enter>键
  2. ngFor用于为单词数组中的每个单词重复input元素
  3. last是一个布尔值,它绑定到一个局部variables,当input是最后一个时,该variables是true
  4. keyup事件绑定到expression式last ? addNewWord() : 0 last ? addNewWord() : 0 。 这确保了只有在从上一个input按下<enter>键时才会添加新的input字段

演示Plnkr

使用内联angular码,在条件画图之后重点:

  <span *ngIf="editId==item.id"> <input #taskEditText type="text" [(ngModel)]="editTask" (keydown.enter)="save()" (keydown.esc)="saveCancel()"/> <button (click)="save()">Save</button> <button (click)="saveCancel()">Cancel</button> {{taskEditText.focus()}} </span> 

为了在初始化同一周期中的几个指令时优先考虑哪个元素将获得焦点,请使用:

指示:

 @Directive({ selector: '[focusOnInit]' }) export class FocusOnInitDirective implements OnInit, AfterViewInit { @Input('focusOnInit') priority: number = 0; static instances: FocusOnInitDirective[] = []; constructor(public renderer: Renderer, public elementRef: ElementRef) { } ngOnInit(): void { FocusOnInitDirective.instances.push(this) } ngAfterViewInit(): void { setTimeout(() => { FocusOnInitDirective.instances.splice(FocusOnInitDirective.instances.indexOf(this), 1); }); if (FocusOnInitDirective.instances.every((i) => this.priority >= i.priority)) { this.renderer.invokeElementMethod( this.elementRef.nativeElement, 'focus', []); } } } 

用法:

 <input type="text" focusOnInit="9"> 

https://plnkr.co/edit/T9VDPIWrVSZ6MpXCdlXF