如何得到角度2的 DOM 元素?

我有一个具有 <p>元素的组件。它的 (click)事件将把它变成一个 <textarea>。因此,用户可以编辑数据。我的问题是:

  • 我怎样才能把注意力集中在 textarea上?
  • 如何获得元素,以便在其上应用 .focus()
  • 我可以避免使用 document.getElemenntById()吗?

我尝试使用“ ElementRef”和“@ViewChild ()”,但似乎遗漏了一些东西:

应用程序组件

@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'
);
}

App.Component. html

<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>
490515 次浏览

使用 翻译: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳,校对: 奇芳# < a href = “ https://angular.io/guide/template-reference-variable”rel = “ nofollow noReferrer”> TemplateVariable ,如下所示,

<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');
}

二零一七年三月二十二日更新

新方法

请注意从 角度 v4.0.0-rc 3(2017-03-10)少数事情已经被改变。 由于角队将废弃 invokeElementMethod,以上代码不再可以使用。

重大改变

从4.0版本开始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不在那里。< em > 附加 img 目前还没有文档记录。

注意: 你可以使用下面的 Rendere2方法(有/没有 ViewChild 变量)来做很多事情。

enter image description here

更新(使用渲染器) :

注意,原始的 Renderer 服务现在已经在 支持 Renderer2

就像在 渲染器2官方文档。上一样

此外,正如@G ünterZöchbauer 所指出的:

实际上使用 ElementRef 就可以了 使用 Renderer2的 ElementRef.nativeElement 是可以的 正在直接访问 elementref.nativeelement.xxx 的属性。


您可以通过使用 elementRefViewChild来实现这一点。但是不推荐使用 elementRef,因为:

  • 安全问题
  • 紧密连接

正如 正式的 ng2文件指出的。

1. 使用 elementRef(直接存取) :

export class MyComponent {
constructor (private _elementRef : ElementRef) {
this._elementRef.nativeElement.querySelector('textarea').focus();
}
}

2. 使用 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;


ngAfterViewInit() {
this.input.nativeElement.focus();


}
}

3. 使用 renderer:

export class MyComponent implements AfterViewInit {
@ViewChild('tasknote') input: ElementRef;
constructor(private renderer: Renderer2){
}


ngAfterViewInit() {
//using selectRootElement instead of depreaced invokeElementMethod
this.renderer.selectRootElement(this.input["nativeElement"]).focus();
}


}

角度2.0.0最终:

我发现使用 ViewChild调节器是最可靠的方法来设置初始形式控制焦点:

@ViewChild("myInput")
set myInput(_input: ElementRef | undefined) {
if (_input !== undefined) {
setTimeout(() => {
this._renderer.invokeElementMethod(_input.nativeElement, "focus");
}, 0);
}
}

Setter 首先用一个 undefined值调用,然后用一个初始化的 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位)。

角度4 + 的更新

Renderer已经被推翻,有利于 Renderer2,但 Renderer2 没有invokeElementMethod。您将需要直接访问 DOM 来设置焦点,就像在 input.nativeElement.focus()中一样。

我仍然发现 ViewChild setter方法工作得最好。当使用 AfterViewInit时,我有时会得到 read property 'nativeElement' of undefined错误。

@ViewChild("myInput")
set myInput(_input: ElementRef | undefined) {
if (_input !== undefined) {
setTimeout(() => { //This setTimeout call may not be necessary anymore.
_input.nativeElement.focus();
}, 0);
}
}