tablas reactivos formularios formulario entre dinamicas comunicacion componentes angular typescript angular-components

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



tablas angular 4 (10)

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

<input #myname>

@ViewChild(''myname'') input;

elemento

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

Ejemplo de StackBlitz

  • @ViewChild() admite la directiva o el 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 <ng-content> ).

descendientes

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

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

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

leer

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

Por ejemplo, ViewContainerRef que requieren los componentes creados dinámicamente en lugar del elemento predeterminado ElementRef

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

suscribir cambios

Aunque los elementos ngAfterViewInit() vista solo se establecen cuando se llama a ngAfterViewInit() y los elementos ngAfterViewInit() contenido solo se establecen cuando se llama a ngAfterContentInit() , si desea suscribirse a los cambios del resultado de la consulta, debe hacerlo 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 de 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 a contenido transcluido

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

Me preguntaba cómo hacerlo en Angular.

Tome el ejemplo del tutorial:

import {Component} from ''@angular/core'' @Component({ selector:''display'' template:` <input #myname(input)="updateName(myname.value)"/> <p>My name : {{myName}}</p> ` }) export class DisplayComponent { myName: string = "Aman"; updateName(input: String) { this.myName = input; } }

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


Para las personas que intentan tomar la instancia del componente dentro de *ngIf o *ngSwitchCase , pueden 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<ElementRef> = new EventEmitter<ElementRef>(); 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 { ... }

Use esta plantilla para obtener la instancia de ElementRef AND MyComponent

<div [ngSwitch]="type"> <wm-my-component #myComponent="myComponent" *ngSwitchCase="Type.MyType" (init)="init($event, myComponent)"> </wm-my-component> </div>

Use este código en TypeScript

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



Selección del elemento objetivo 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:

<ul *ngFor="let event of listEvents; let i = index"> <li (click)="selectElement(event.name, i)" [class]="event.class"> {{ event.name }} </li>

código css:

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


importe el decorador ViewChild desde @angular/core , así:

Código HTML:

<form #f="ngForm"> ... ... </form>

Código TS:

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

ahora puede usar el objeto ''myForm'' para acceder a cualquier elemento dentro de él en la clase.

Source


para obtener el próximo hermano inmediato, use esto

event.source._elementRef.nativeElement.nextElementSibling


Nota : Esto no se aplica a Angular 6 y superior, ya que ElementRef convirtió en ElementRef<T> con T denota el tipo de nativeElement .

Me gustaría agregar que si está usando ElementRef , como lo recomiendan todas las respuestas, inmediatamente se encontrará con el problema de que ElementRef tiene una declaración 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 elemento HTMLElement .

Para solucionar esto, 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) { } }


Angular 4+ : use renderer.selectRootElement con un selector 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, el formulario se ampliará 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 poner el foco en el campo de notas del proyecto si son clientes existentes, o en el campo de nombre si son nuevos.

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

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

Dado que lo único que estoy haciendo es establecer el foco en un elemento, no necesito preocuparme por la detección de cambios, por lo que puedo ejecutar la llamada a renderer.selectRootElement fuera de Angular. Debido a que necesito dar tiempo a las nuevas secciones para que se procesen, la sección del elemento se ajusta en un tiempo de espera para permitir que los subprocesos de procesamiento se pongan 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 básicos de CSS.

Sé que este ejemplo se ocupó principalmente del evento de enfoque, pero es difícil para mí que esto no pueda usarse en otros contextos.


import { Component, ElementRef, OnInit } from ''@angular/core''; @Component({ selector:''display'', template:` <input (input)="updateName($event.target.value)"> <p> My name : {{ myName }}</p> ` }) 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, here


*/ import {Component,ViewChild} from ''@angular/core'' /*Import View Child*/ @Component({ selector:''display'' template:` <input #myname (input) = "updateName(myname.value)"/> <p> My name : {{myName}}</p> ` }) 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*/ }; } }