¿Cómo puedo seleccionar un elemento en una plantilla de componente?

¿Alguien sabe cómo hacerse con un elemento definido en una plantilla de componente? El polymer lo hace realmente fácil con $ y $$ .

Me preguntaba cómo hacerlo en Angular.

Toma el ejemplo del tutorial:

 import {Component} from '@angular/core' @Component({ selector:'display' template:`  

My name : {{myName}}

` }) export class DisplayComponent { myName: string = "Aman"; updateName(input: String) { this.myName = input; } }

¿Cómo atrapo una referencia del p o elemento de input desde dentro de la definición de la clase?

En lugar de inyectar ElementRef y usar querySelector o similar desde allí, se puede usar una forma declarativa para acceder directamente a los elementos en la vista:

  
 @ViewChild('myname') input; 

elemento

 ngAfterViewInit() { console.log(this.input.nativeElement.value); } 

Ejemplo de StackBlitz

  • @ViewChild () admite directiva o tipo de componente como parámetro, o el nombre (cadena) de una variable de plantilla.
  • @ViewChildren () también admite una lista de nombres como lista separada por comas (actualmente no se permiten espacios @ViewChildren('var1,var2,var3') ).
  • @ContentChild () y @ContentChildren () hacen lo mismo pero a la luz DOM ( elementos proyectados).

descendientes

@ContentChildren() es el único que permite consultar también descendientes

 @ContentChildren(SomeTypeOrVarName, {descendants: true}) someField; 

{descendants: true} debería ser el predeterminado pero no está en 2.0.0 final y se considera un error
Esto fue arreglado en 2.0.1

leer

Si hay un componente y directivas, el parámetro de read permite especificar qué instancia debe devolverse.

Por ejemplo, ViewContainerRef que es requerido por los componentes creados dinámicamente en lugar del ElementRef predeterminado

 @ViewChild('myname', { read: ViewContainerRef }) target; 

suscribirse cambios

Aunque view children solo están configurados cuando se ngAfterViewInit() y los elementos ngAfterViewInit() contenido solo se configuran cuando se ngAfterContentInit() , si desea suscribirse a cambios del resultado de la consulta, debe hacerse en ngOnInit()

https://github.com/angular/angular/issues/9689#issuecomment-229247134

 @ViewChildren(SomeType) viewChildren; @ContentChildren(SomeType) contentChildren; ngOnInit() { this.viewChildren.changes.subscribe(changes => console.log(changes)); this.contentChildren.changes.subscribe(changes => console.log(changes)); } 

acceso DOM directo

solo puede consultar elementos DOM, pero no componentes o instancias directivas:

 export class MyComponent { constructor(private elRef:ElementRef) {} ngAfterViewInit() { var div = this.elRef.nativeElement.querySelector('div'); console.log(div); } // for transcluded content ngAfterContentInit() { var div = this.elRef.nativeElement.querySelector('div'); console.log(div); } } 

obtener contenido proyectado arbitrario

Ver acceso contenido transcluido

Puede obtener un control del elemento DOM a través de ElementRef inyectándolo en el constructor de su componente:

 constructor(myElement: ElementRef) { ... } 

Documentos: https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html

 import { Component, ElementRef, OnInit } from '@angular/core'; @Component({ selector:'display', template:`  

My name : {{ myName }}

` }) class DisplayComponent implements OnInit { constructor(public element: ElementRef) { this.element.nativeElement // <- your direct element reference } ngOnInit() { var el = this.element.nativeElement; console.log(el); } updateName(value) { // ... } }

Ejemplo actualizado para trabajar con la última versión

Para más detalles sobre el elemento nativo, aquí

Angular 4+ : use renderer.selectRootElement con un selector de CSS para acceder al elemento.

Tengo un formulario que inicialmente muestra una entrada de correo electrónico. Después de ingresar el correo electrónico, se expandirá el formulario para permitirles continuar agregando información relacionada con su proyecto. Sin embargo, si no son un cliente existente, el formulario incluirá una sección de dirección sobre la sección de información del proyecto.

A partir de ahora, la parte de entrada de datos no se ha dividido en componentes, por lo que las secciones se administran con directivas * ngIf. Necesito enfocarme en el campo de notas del proyecto si son un cliente existente, o en el campo del primer nombre si son nuevos.

Probé las soluciones sin éxito. Sin embargo, la Actualización 3 en esta respuesta me dio la mitad de la solución final. La otra mitad vino de la respuesta de MatteoNY en este hilo. El resultado es esto:

 import { NgZone, Renderer } from '@angular/core'; constructor(private ngZone: NgZone, private renderer: Renderer) {} setFocus(selector: string): void { this.ngZone.runOutsideAngular(() => { setTimeout(() => { this.renderer.selectRootElement(selector).focus(); }, 0); }); } submitEmail(email: string): void { // Verify existence of customer ... if (this.newCustomer) { this.setFocus('#firstname'); } else { this.setFocus('#description'); } } 

Como lo único que estoy haciendo es centrarme en un elemento, no necesito preocuparme por la detección de cambios, así que puedo ejecutar la llamada a renderer.selectRootElement fuera de Angular. Debido a que tengo que dar tiempo a las nuevas secciones para procesar, la sección del elemento se envuelve en un tiempo de espera para permitir que el tiempo de los subprocesos de procesamiento se ponga al día antes de que se intente la selección del elemento. Una vez que todo está configurado, simplemente puedo llamar al elemento usando selectores CSS básicos.

Sé que este ejemplo se trató principalmente con el evento de enfoque, pero es difícil para mí que esto no se pueda usar en otros contextos.

Para las personas que intenten capturar la instancia del componente dentro de *ngIf o *ngSwitchCase , puede seguir este truco.

Crea una directiva init .

 import { Directive, EventEmitter, Output, OnInit, ElementRef } from '@angular/core'; @Directive({ selector: '[init]' }) export class InitDirective implements OnInit { constructor(private ref: ElementRef) {} @Output() init: EventEmitter = new EventEmitter(); ngOnInit() { this.init.emit(this.ref); } } 

Exporte su componente con un nombre como myComponent

 @Component({ selector: 'wm-my-component', templateUrl: 'my-component.component.html', styleUrls: ['my-component.component.css'], exportAs: 'myComponent' }) export class MyComponent { ... } 

Utilice esta plantilla para obtener la instancia de ElementRef AND MyComponent

 

Use este código en TypeScript

 init(myComponentRef: ElementRef, myComponent: MyComponent) { } 

importe el decorador de ViewChild desde @ angular / core, de esta forma:

 
...
import { ViewChild } from '@angular/core'; class TemplateFormComponent { @ViewChild('f') myForm: any; . . . }

ahora puedes usar el objeto ‘myForm’ para acceder a cualquier elemento dentro de él en la clase.

fuente: https://codecraft.tv/courses/angular/forms/template-driven/

  */ import {Component,ViewChild} from '@angular/core' /*Import View Child*/ @Component({ selector:'display' template:`  

My name : {{myName}}

` }) export class DisplayComponent{ @ViewChild('myname')inputTxt:ElementRef; /*create a view child*/ myName: string; updateName: Function; constructor(){ this.myName = "Aman"; this.updateName = function(input: String){ this.inputTxt.nativeElement.value=this.myName; /*assign to it the value*/ }; } }

Me gustaría agregar que si está utilizando ElementRef , como lo recomiendan todas las respuestas, inmediatamente se encontrará con el problema de que ElementRef tiene una statement de tipo horrible que se parece a

 export declare class ElementRef { nativeElement: any; } 

esto es estúpido en un entorno de navegador donde nativeElement es un HTMLElement .

Para solucionarlo, puede usar la siguiente técnica

 import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core'; interface ElementRef { nativeElement: HTMLElement; } @Component({...}) export class MyComponent { constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { } } 

para obtener el próximo hermano inmediato, usa esto

 event.source._elementRef.nativeElement.nextElementSibling 

Seleccionar el elemento objective de la lista. Es fácil seleccionar un elemento particular de la lista de los mismos elementos.

código de componente:

 export class AppComponent { title = 'app'; listEvents = [ {'name':'item1', 'class': ''}, {'name':'item2', 'class': ''}, {'name':'item3', 'class': ''}, {'name':'item4', 'class': ''} ]; selectElement(item: string, value: number) { console.log("item="+item+" value="+value); if(this.listEvents[value].class == "") { this.listEvents[value].class='selected'; } else { this.listEvents[value].class= ''; } } } 

código HTML:

 
  • {{ event.name }}

código css:

 .selected { color: red; background:blue; }