如何自动对焦输入元素?与this问题类似,但与AngularDart不同。像这样:
<input type="text" [(ngModel)]="title" [focus] />
//or
<input type="text" [(ngModel)]="title" autofocus />
Angular2是否支持此功能?
最近的问题是this one,但有没有更短/更简单的解决方案,因为我没有“输入框列表”。在提供的链接中使用*ngFor="#input of inputs"
,但我在控件模板中只有1个输入。
答案 0 :(得分:57)
这是我目前的代码:
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;
}
}
用例:
[autofocus] //will focus
[autofocus]="true" //will focus
[autofocus]="false" //will not focus
过时的代码(旧答案,以防万一):
我最终得到了这段代码:
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', []);
}
}
如果我将代码放在ngOnViewInit
中,则无效。代码也使用最佳实践,因为直接调用元素不是recommended。
已编辑(有条件自动对焦):
几天前我需要条件自动对焦,因为我隐藏了第一个自动对焦元素,我想要聚焦另一个,但只有当第一个不可见时,我才结束这段代码:
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 is deprecated和新的Renderer2不支持它。
所以我们回归本地焦点(例如,它不能在DOM之外工作 - 例如SSR!)。
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;
}
}
用例:
[autofocus] //will focus
[autofocus]="true" //will focus
[autofocus]="false" //will not focus
答案 1 :(得分:34)
autofocus
是一个原生的html功能,至少应该用于页面初始化。但是,它无法与许多角度场景一起使用,尤其是使用*ngIf
。
您可以制作一个非常简单的自定义指令来获得所需的行为。
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();
}
}
上述指令适用于我的用例。
如何使用
<input *ngIf="someCondition" myAutofocus />
编辑:似乎有一些用例,在OnInit
生命周期方法中尽早调用焦点。如果是这种情况,请改为OnAfterViewInit
。
答案 2 :(得分:14)
以下指令适用于我使用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();
}
}
像这样使用它:
<md-input-container>
<input mdInput placeholder="Item Id" formControlName="itemId" name="itemId" myAutofocus>
</md-input-container>
使用OnInit生命周期事件的选项对我不起作用。我也尝试在另一个对我不起作用的答案中使用渲染器。
答案 3 :(得分:13)
<input type="text" [(ngModel)]="title" #myInput />
{{ myInput.focus() }}
在模板中输入后立即添加 {{myInput.focus()}}
答案 4 :(得分:12)
您可以为input元素指定模板引用变量#myInput
:
<input type="text" [(ngModel)]="title" #myInput />
让您的组件实现AfterViewInit
,使用ViewChild
注释获取输入元素的引用,并将您的元素集中在ngAfterViewInit
钩子中:
export class MyComponent implements AfterViewInit {
@ViewChild("myInput") private _inputElement: ElementRef;
[...]
ngAfterViewInit(): void {
this._inputElement.nativeElement.focus();
}
}
答案 5 :(得分:3)
从IE11开始,像其他所有现代浏览器一样,输入的本机HTML autofocus Attribute应该也可以正常工作,而无需使用Angular:
<input autofocus>
<input type="text" [(ngModel)]="title" autofocus>
答案 6 :(得分:1)
如果您不需要对/错功能,但始终需要设置自动对焦,那么Makla解决方案的实现方式会更短:
autofocus.directive.ts:
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
@Directive({
selector: '[autofocus]'
})
export class AutofocusDirective implements AfterViewInit {
constructor(private el: ElementRef) {
}
ngAfterViewInit() {
// Otherwise Angular throws error: Expression has changed after it was checked.
window.setTimeout(() => {
this.el.nativeElement.focus();
});
}
}
用例:
<input autofocus> //will focus
使用AfterViewInit代替OnInit可以将光标放置在输入字段中的内容之后(如果填充了该光标)。
记住要在模块中声明并导出您的指令!
答案 7 :(得分:1)
尝试这个简单但有效的功能。
function addFocusInput() {
document.getElementById('text-focus').focus();
}
addFocusInput();
<input id="text-focus" type="text" placeholder=""/>
答案 8 :(得分:0)
我知道这是一篇旧文章,但对于其他寻求新答案的人: 我正在使用角度材质对话框,它是自动选择关闭按钮而不是输入。
使用cdk-focus-start
(CDK的一部分)可以解决此问题,而无需其他代码。
答案 9 :(得分:0)
我的解决方案:
<input type="text" id="searchInput">
// put focus on element with id 'searchInput', try every 100ms and retry 30 times
this.focus('searchInput',30,100);
focus( idElement:string, maxNbRetries:number, intervalMs:number){
let nbRetries = 0;
let elt = null;
const stop$ = new Subject<boolean>();
const source = interval(intervalMs);
const source$ = source.pipe(
tap(item=>{
elt = document.getElementById(idElement);
nbRetries++;
if(nbRetries>maxNbRetries){
stop$.next(true);
console.log(`unable to put the focus on the element !`)
}
}),
filter(item=>elt !=null),
map(item=>{
elt.focus();
stop$.next(true);
}),
takeUntil(stop$)
).subscribe();
}
焦点不适用于角度生命周期。为了将其强制在字段上,我运行了一个可观察到的对象,该对象发出了每个“ intervalMs”。如果该元素已经渲染,我可以通过其ID找到它。之后,我可以设置焦点。 如果找到nbRetries> maxNbRetries或元素ID,我将使用takeUntil运算符停止可观察对象。