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