如何获得angular2的DOM元素
我有一个有p
元素的组件。 它的onClick
事件会将其更改为textarea
以便用户可以编辑数据。 我的问题是:
- 我怎么能把重点放在textarea上?
- 我怎么能到达这个元素,所以我可以appy上的.focus()?
- 我可以避免使用document.getElemenntById()?
我试图使用“ElementRef”和“@ViewChild()”,但似乎我失去了一些东西:
// ------ THE CLASS @ViewChild('tasknoteId') taskNoteRef:ElementRef; noteEditMode: boolean = false; get isShowNote (){ return !this.noteEditMode && this.todo.note ? true : false; } taskNote: string; toggleNoteEditMode () { this.noteEditMode = !this.noteEditMode; this.renderer.invokeElementMethod(this.taskNoteRef.nativeElement,'focus'); } // ------ THE COMPONENT <span class="the-insert"> <form [hidden]="!noteEditMode && todo.note"> <textarea #tasknoteId id="tasknote" name="tasknote" [(ngModel)]="todo.note" placeholder="{{ notePlaceholder }}" style="background-color:pink" (blur)="updateNote()" (click)="toggleNoteEditMode()" [autofocus]="noteEditMode" [innerHTML]="todo.note"> </textarea> </form> </span>
如下所示,使用ViewChild和#localvariable ,
<textarea #someVar id="tasknote" name="tasknote" [(ngModel)]="taskNote" placeholder="{{ notePlaceholder }}" style="background-color: pink" (blur)="updateNote() ; noteEditMode = false " (click)="noteEditMode = false"> {{ todo.note }} </textarea>
在组件中,
最老的方式
import {ElementRef} from '@angular/core'; @ViewChild('someVar') el:ElementRef; ngAfterViewInit() { this.el.nativeElement.focus(); }
老方法
import {ElementRef} from '@angular/core'; @ViewChild('someVar') el:ElementRef; constructor(private rd: Renderer) {} ngAfterViewInit() { this.rd.invokeElementMethod(this.el.nativeElement,'focus'); }
更新于22/03(三月)/ 2017
新方法
请注意,从Angular v4.0.0-rc.3(2017-03-10)几件事情已经改变。 由于Angular团队会弃用invokeElementMethod
,因此上面的代码不再可以使用。
打破变化
自4.0 rc.1:
将RendererV2重命名为Renderer2
将RendererTypeV2重命名为RendererType2
将RendererFactoryV2重命名为RendererFactory2
import {ElementRef,Renderer2} from '@angular/core'; @ViewChild('someVar') el:ElementRef; constructor(private rd: Renderer2) {} ngAfterViewInit() { console.log(this.rd); this.el.nativeElement.focus(); //<<<=====same as oldest way }
console.log(this.rd)
会给你以下方法,你现在可以看到invokeElementMethod
不存在。 附加IMG,但没有logging。
注意:您可以使用Rendere2
以下方法来使用/不使用ViewChildvariables来执行许多操作。
更新(2017年9月10日):
请注意,原来的Renderer服务现在已经被弃用,以支持Renderer2
就像Renderer2官方文档一样。
此外,正如@GünterZöchbauer所指出的那样:
其实使用ElementRef就好了。 在Renderer2中使用ElementRef.nativeElement也没问题。 不鼓励直接访问ElementRef.nativeElement.xxx的属性。
您可以通过使用elementRef
以及elementRef
来实现此ViewChild
。 但是不build议使用elementRef
因为:
- 安全问题
- 紧耦合
正如ng2文档所指出的那样。
使用elementRef
(直接访问):
export class MyComponent { constructor (private _elementRef : elementRef) { this._elementRef.nativeElement.querySelector('textarea').focus(); } }
使用ViewChild
( 更好的方法 ):
<textarea #tasknote name="tasknote" [(ngModel)]="taskNote" placeholder="{{ notePlaceholder }}" style="background-color: pink" (blur)="updateNote() ; noteEditMode = false " (click)="noteEditMode = false"> {{ todo.note }} </textarea> // <-- changes id to local var export class MyComponent implements AfterViewInit { @ViewChild('tasknote') input: ElementRef; constructor(private renderer: Renderer2) {} //<-- changed to Renderer2 ngAfterViewInit() { this.input.nativeElement.focus(); } }
Angular 2.0.0 Final:
我发现使用ViewChild
setter是设置初始表单控件焦点的最可靠的方法:
@ViewChild("myInput") set myInput(_input: ElementRef | undefined) { if (_input !== undefined) { setTimeout(() => { this._renderer.invokeElementMethod(_input.nativeElement, "focus"); }, 0); } }
首先使用undefined
值调用setter,然后使用初始化的ElementRef
调用。
在这里工作的例子和完整的源代码: http : //plnkr.co/edit/u0sLLi?p=preview
使用TypeScript 2.0.3 Final / RTM,Angular 2.0.0 Final / RTM和Chrome 53.0.2785.116 m(64位)。