navigationend - Elemento de entrada de enfoque automático Angular2+
router events angular 6 (5)
¿Cómo puedo autoenfocar el elemento de entrada? Similar a this pregunta, pero no con AngularDart. Algo como esto:
<input type="text" [(ngModel)]="title" [focus] />
//or
<input type="text" [(ngModel)]="title" autofocus />
¿Tiene Angular2 alguna versión compatible con esta característica?
La mejor pregunta cercana es esta , pero ¿hay alguna solución más corta / más fácil, ya que no tengo "lista de cuadros de entrada"? En el enlace proporcionado *ngFor="#input of inputs"
se usa, pero solo tengo 1 entrada en la plantilla de control.
Este es mi código actual:
import { Directive, ElementRef, Input } from "@angular/core";
@Directive({
selector: "[autofocus]"
})
export class AutofocusDirective
{
private focus = true;
constructor(private el: ElementRef)
{
}
ngOnInit()
{
if (this.focus)
{
//Otherwise Angular throws error: Expression has changed after it was checked.
window.setTimeout(() =>
{
this.el.nativeElement.focus(); //For SSR (server side rendering) this is not safe. Use: https://github.com/angular/angular/issues/15008#issuecomment-285141070)
});
}
}
@Input() set autofocus(condition: boolean)
{
this.focus = condition !== false;
}
}
caso de uso:
[autofocus] //will focus
[autofocus]="true" //will focus
[autofocus]="false" //will not focus
Código obsoleto (respuesta anterior, por si acaso):
Terminé con este código:
import {Directive, ElementRef, Renderer} from ''@angular/core'';
@Directive({
selector: ''[autofocus]''
})
export class Autofocus
{
constructor(private el: ElementRef, private renderer: Renderer)
{
}
ngOnInit()
{
}
ngAfterViewInit()
{
this.renderer.invokeElementMethod(this.el.nativeElement, ''focus'', []);
}
}
Si pongo el código en ngOnViewInit
, no funciona. El código también usa las mejores prácticas, ya que no se recommended llamar al elemento directamente.
Editado (autofocus condicional):
Hace unos días necesité el enfoque automático condicional, porque oculté el primer elemento de enfoque automático y deseo enfocar otro, pero solo cuando el primero no está visible, y terminé con este código:
import { Directive, ElementRef, Renderer, Input } from ''@angular/core'';
@Directive({
selector: ''[autofocus]''
})
export class AutofocusDirective
{
private _autofocus;
constructor(private el: ElementRef, private renderer: Renderer)
{
}
ngOnInit()
{
}
ngAfterViewInit()
{
if (this._autofocus || typeof this._autofocus === "undefined")
this.renderer.invokeElementMethod(this.el.nativeElement, ''focus'', []);
}
@Input() set autofocus(condition: boolean)
{
this._autofocus = condition != false;
}
}
Edited2:
Renderer.invokeElementMethod está en desuso y el nuevo Renderer2 no lo admite. Así que volvemos al enfoque nativo (¡que no funciona fuera de DOM - SSR, por ejemplo!).
import { Directive, ElementRef, Input } from ''@angular/core'';
@Directive({
selector: ''[autofocus]''
})
export class AutofocusDirective
{
private _autofocus;
constructor(private el: ElementRef)
{
}
ngOnInit()
{
if (this._autofocus || typeof this._autofocus === "undefined")
this.el.nativeElement.focus(); //For SSR (server side rendering) this is not safe. Use: https://github.com/angular/angular/issues/15008#issuecomment-285141070)
}
@Input() set autofocus(condition: boolean)
{
this._autofocus = condition != false;
}
}
caso de uso:
[autofocus] //will focus
[autofocus]="true" //will focus
[autofocus]="false" //will not focus
La siguiente directiva funciona para mí usando Angular 4.0.1
import {Directive, ElementRef, AfterViewInit} from ''@angular/core'';
@Directive({
selector: ''[myAutofocus]''
})
export class MyAutofocusDirective implements AfterViewInit {
constructor(private el: ElementRef)
{
}
ngAfterViewInit()
{
this.el.nativeElement.focus();
}
}
Úselo así:
<md-input-container>
<input mdInput placeholder="Item Id" formControlName="itemId" name="itemId" myAutofocus>
</md-input-container>
La opción de usar el evento de ciclo de vida OnInit no funcionó para mí. También intenté usar el Renderer en la otra respuesta que no funcionó para mí.
Podría asignar al elemento de entrada una variable de referencia de plantilla #myInput
:
<input type="text" [(ngModel)]="title" #myInput />
Deje que su componente implemente AfterViewInit
, tome la referencia al elemento con la anotación ViewChild
y enfoque su elemento en el gancho ngAfterViewInit
:
export class MyComponent implements AfterViewInit {
@ViewChild("myInput")
private _inputElement: ElementRef;
[...]
ngAfterViewInit(): void {
_inputElement.nativeElement.focus();
}
}
autofocus
es una función html nativa que debería funcionar al menos para la inicialización de la página. Sin embargo, no funciona con muchos escenarios angulares, especialmente con *ngIf
.
Puede hacer una directiva personalizada realmente simple para obtener el comportamiento deseado.
import { Directive, OnInit, ElementRef } from ''@angular/core'';
@Directive({
selector: ''[myAutofocus]''
})
export class AutofocusDirective implements OnInit {
constructor(private elementRef: ElementRef) { };
ngOnInit(): void {
this.elementRef.nativeElement.focus();
}
}
La directiva anterior funciona para mis casos de uso.
Cómo utilizar
<input *ngIf="someCondition" myAutofocus />
EDITAR: Parece haber usos en los que es temprano para llamar al foco en el método del ciclo de vida OnInit
. Si ese es el caso, cambie a OnAfterViewInit
en OnAfterViewInit
lugar.
<input type="text" [(ngModel)]="title" #myInput />
{{ myInput.focus() }}
simplemente agregue {{myInput.focus ()}} justo después de la entrada dentro de la plantilla