En mi aplicación, traté de colocar un botón que muestra/oculta un campo de input con una propiedad de componente boolean . Si el botón muestra la input , el enfoque debe establecerse en la input . Pero parece que no funciona. Si *ngIf , la directiva de enfoque funciona bien.
Creé un plunker que muestra lo que quiero decir. Es un poco difícil describir mi problema.
HTML en un componente:
<input *ngIf="filterShow.options" [focus]="filterFocus.options" [(ngModel)]="filter.options"> <button type="button" (click)="setShowFilter('options')"> focus </button> método setShowFilter() :
private setShowFilter(filter: string) { this.filterShow[filter] = !this.filterShow[filter]; /* reset filter */ this.filter[filter] = ""; this.filterFocus[filter].emit(true); } focus.directive.ts :
@Directive({ selector: '[focus]' }) export class FocusDirective implements OnInit { @Input('focus') focusEvent: EventEmitter<boolean>; constructor(private elementRef : ElementRef, private renderer : Renderer ) { } ngOnInit() { this.focusEvent.subscribe(event => { this.renderer .invokeElementMethod(this.elementRef.nativeElement, 'focus', []); }); } }EventEmitter s son para @Output s, no para @Input s. Prueba algo como esto en su lugar:
@Directive({ selector: '[focus]' }) export class FocusDirective implements OnChanges { @Input('focus') focus: boolean; constructor(private elementRef : ElementRef, private renderer : Renderer ) { } ngOnChanges() { if (this.focus) { this.renderer .invokeElementMethod(this.elementRef.nativeElement, 'focus', []); } } }La mayoría de las veces, no funciona porque el evento de enfoque es seguido por otros eventos. Así que el elemento perdió el foco. Necesitamos usar setTimeout para ponerlo al final de la cola del Programador de tareas:
import { Directive, OnChanges, Input, ElementRef } from "@angular/core"; @Directive({ selector: '[focus]' }) export class FocusDirective implements OnChanges { @Input('focus') focus: boolean; constructor(private elementRef : ElementRef) { } ngOnChanges() { if (this.focus) { setTimeout(() => { this.elementRef.nativeElement.focus(); }, 0); } } }Una forma más limpia de lograr esto sin tener que usar una directiva es usar <label> en lugar de <button> y usar css para diseñarlo como un botón. Por ejemplo,
<label for="myInput"></label> <input id="myInput"></input>
De esta manera, puede lograr el enfoque incluso con la presencia de *ngIf porque <input> ahora está vinculado a <label> . Además, el sitio web de documentación de Angular2 advierte sobre el uso de ElementRef debido a la vulnerabilidad de seguridad que presenta.