如何获得角度2的dom元素

时间:2016-08-14 17:25:52

标签: angular

我有一个具有p元素的组件。其onClick事件会将其更改为textarea,以便用户可以编辑数据。我的问题是:

  • 我如何能够专注于textarea?
  • 我如何才能到达元素,以便我可以在其上应用.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>

2 个答案:

答案 0 :(得分:66)

更新(使用渲染器):

  

请注意,现在已弃用原始渲染器服务   Renderer2的青睐

on Renderer2 official doc.

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

  

实际上使用ElementRef就好了。也用   使用Renderer2的ElementRef.nativeElement很好。什么是气馁   正在直接访问ElementRef.nativeElement.xxx的属性。

您可以使用elementRef以及ViewChild来实现此目的。但由于以下原因,不建议使用elementRef

  • 安全问题
  • 紧耦合

正如official ng2 documentation所指出的那样。

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

    }

答案 1 :(得分:10)

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位)。

Angular 4 +的更新

Renderer已弃用,仅支持Renderer2Renderer2 does not have 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);
    }
}