How to get `DOM Element` in Angular 2?

Bastian picture Bastian · Aug 14, 2016 · Viewed 377.5k times · Source

I have a component that has a <p> element. It's (click) event will change it into a <textarea>. So, the user can edit the data. My question is:

  • How can I make the focus on the textarea?
  • How can I get the element, so I can apply the .focus() on it?
  • Can I avoid using document.getElemenntById()?

I have tried to use the "ElementRef" and the "@ViewChild()" however it seems that I'm missing something:

app.component.ts

@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>

Answer

micronyks picture micronyks · Aug 14, 2016

Use ViewChild with #localvariable as shown here,

<textarea  #someVar  id="tasknote"
                  name="tasknote"
                  [(ngModel)]="taskNote"
                  placeholder="{{ notePlaceholder }}"
                  style="background-color: pink"
                  (blur)="updateNote() ; noteEditMode = false " (click)="noteEditMode = false"> {{ todo.note }} 

</textarea>

In component,

OLDEST Way

import {ElementRef} from '@angular/core';
@ViewChild('someVar') el:ElementRef;

ngAfterViewInit()
{
   this.el.nativeElement.focus();
}


OLD Way

import {ElementRef} from '@angular/core';
@ViewChild('someVar') el:ElementRef;

constructor(private rd: Renderer) {}
ngAfterViewInit() {
    this.rd.invokeElementMethod(this.el.nativeElement,'focus');
}


Updated on 22/03(March)/2017

NEW Way

Please note from Angular v4.0.0-rc.3 (2017-03-10) few things have been changed. Since Angular team will deprecate invokeElementMethod, above code no longer can be used.

BREAKING CHANGES

since 4.0 rc.1:

rename RendererV2 to Renderer2
rename RendererTypeV2 to RendererType2
rename RendererFactoryV2 to 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) will give you following methods and you can see now invokeElementMethod is not there. Attaching img as yet it is not documented.

NOTE: You can use following methods of Rendere2 with/without ViewChild variable to do so many things.

enter image description here