Como obter o "elemento DOM" no Angular 2? [duplicado]

tenho um componente que tem um elemento <p>. É um evento que vai transformá-lo num evento. Então, o usuário pode editar os dados. A minha pergunta é:

    Como posso concentrar-me no textarea? Como posso obter o elemento, para poder aplicar o .focus() nele? Posso evitar usar document.getElemenntById()?

tentei usar o "ElementRef" e o "@ViewChild () " no entanto parece que me está a escapar algo:

App.componente.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.componente.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>
 148
Author: ng-hobby, 2016-08-14

3 answers

Utilizar ViewChild com #localvariável Como mostrado aqui,

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

</textarea>

Em componente,

A maneira mais antiga

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

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


À maneira antiga

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

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


actualizado em 22/03 (Março)/2017

Novo Caminho

Por favor, a ter em conta em Angular v4. 0. 0-rc.3 (2017-03-10) poucas coisas foram alteradas. Uma vez que a equipa Angular vai depreciar invokeElementMethod, o código acima não pode mais ser usado.

A QUEBRAR AS MUDANÇAS

Desde 4.0 rc.1:

Mudar o nome do RendererV2 para Renderer2
mudar o nome do RendererTypeV2 para RendererType2
mudar o nome de RendererFactoryV2 para 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) dar-lhe-á os seguintes métodos e você pode ver agora invokeElementMethod não está lá. anexar img ainda não está documentado.

Nota: pode utilizar os seguintes métodos de Rendere2 Com / Sem criança de vista variável para fazer tantas coisas.

enter image description here

 198
Author: micronyks, 2017-03-22 10:53:44

Actualizar (usando a representação):

Note que o serviço original do renderizador foi agora desactualizado em favor do Renderer2

As on Rendererer2 oficial doc.

Além disso, como apontado por @GünterZöchbauer:

Na verdade, usar ElementRef é óptimo. Usar também ElementRef.nativeElement with Renderer2 is fine. O que é desanimado está acessando propriedades do ElementRef.nativeElement.x directamente.


Você pode conseguir isso usando elementRef bem como por ViewChild. no entanto, não é recomendável utilizar elementRef devido a:

  • questão de segurança
  • engate apertado

Conforme indicado pela documentação oficial do ng2 .

1. Utilizar elementRef (Acesso Directo):

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

2. Utilização ViewChild (melhor abordagem):

<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. Utilização 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();
      }

    }
 81
Author: candidJ, 2020-06-17 06:07:13

Angular 2.0.0 Final:

Descobri que a utilização de um ViewChild setter é a forma mais fiável de definir o foco inicial de controlo da forma:

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

O setter é chamado primeiro com um valor undefined seguido por uma chamada com um ElementRef inicializado.

Exemplo de trabalho e fonte completa aqui: http://plnkr.co/edit/u0sLLi?p=preview

usando TypeScript 2.0.3 Final/RTM, Angular 2.0.0 Final / RTM, e Chrome 53.0.2785.116 m (64-bit).

Actualizar para o Angular 4+

Renderer foi desacreditado a favor de Renderer2, mas Renderer2 não tem O invokeElementMethod. Você precisará acessar o DOM diretamente para definir o foco como em input.nativeElement.focus().

Continuo a achar que a abordagem da criança de visão funciona melhor. Ao usar AfterViewInit às vezes tenho read property 'nativeElement' of undefined erro.
@ViewChild("myInput")
set myInput(_input: ElementRef | undefined) {
    if (_input !== undefined) {
        setTimeout(() => { //This setTimeout call may not be necessary anymore.
            _input.nativeElement.focus();
        }, 0);
    }
}
 11
Author: KTCO, 2017-12-06 23:52:21