如何使用 Angular4 通过元素 id 设置焦点
How to use Angular4 to set focus by element id
我是 Angular 的新手,我正在尝试使用它来将焦点设置在 ID 为 "input1" 的输入上。我正在使用以下代码:
@ViewChild('input1') inputEl: ElementRef;
然后在后面的组件中:
this.inputEl.nativeElement.focus();
但它不起作用。我究竟做错了什么?任何帮助将不胜感激。
组件
import { Component, ElementRef, ViewChild, AfterViewInit} from '@angular/core';
...
@ViewChild('input1', {static: false}) inputEl: ElementRef;
ngAfterViewInit() {
setTimeout(() => this.inputEl.nativeElement.focus());
}
HTML
<input type="text" #input1>
@Z.Bagley提到的问题中的一个答案给了我答案。我必须将 Renderer2 从 @angular/core 导入到我的组件中。那么:
const element = this.renderer.selectRootElement('#input1');
setTimeout(() => element.focus(), 0);
谢谢@MrBlaise 的解决方案!
我也遇到了同样的问题,经过一些搜索我找到了一个很好的解决方案,因为@GreyBeardedGeek 提到 setTimeout 是这个 solution.He 的关键是完全正确的。在您的方法中,您只需添加 setTimeout 即可解决您的问题。
setTimeout(() => this.inputEl.nativeElement.focus(), 0);
这是一个 Angular4+ 指令,您可以在任何组件中 re-use。基于 Niel T 在 .
的回答中给出的代码
import { NgZone, Renderer, Directive, Input } from '@angular/core';
@Directive({
selector: '[focusDirective]'
})
export class FocusDirective {
@Input() cssSelector: string
constructor(
private ngZone: NgZone,
private renderer: Renderer
) { }
ngOnInit() {
console.log(this.cssSelector);
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
this.renderer.selectRootElement(this.cssSelector).focus();
}, 0);
});
}
}
您可以像这样在组件模板中使用它:
<input id="new-email" focusDirective cssSelector="#new-email"
formControlName="email" placeholder="Email" type="email" email>
给输入一个id并将id传递给指令的cssSelector
属性。或者你可以传递任何你喜欢的 cssSelector。
Niel T 的评论:
Since the only thing I'm doing is setting the focus on an element, I
don't need to concern myself with change detection, so I can actually
run the call to renderer.selectRootElement outside of Angular. Because
I need to give the new sections time to render, the element section is
wrapped in a timeout to allow the rendering threads time to catch up
before the element selection is attempted. Once all that is setup, I
can simply call the element using basic CSS selectors.
这对我有帮助(在离子中,但想法是一样的)
https://mhartington.io/post/setting-input-focus/
在模板中:
<ion-item>
<ion-label>Home</ion-label>
<ion-input #input type="text"></ion-input>
</ion-item>
<button (click)="focusInput(input)">Focus</button>
在控制器中:
focusInput(input) {
input.setFocus();
}
这是一个可以在任何组件中使用的指令:
import { NgZone, Directive, ElementRef, AfterContentInit, Renderer2 } from '@angular/core';
@Directive({
selector: '[appFocus]'
})
export class FocusDirective implements AfterContentInit {
constructor(private el: ElementRef, private zone: NgZone, private renderer: Renderer2) {}
ngAfterContentInit() {
this.zone.runOutsideAngular(() => setTimeout(() => {
this.renderer.selectRootElement(this.el.nativeElement).focus();
}, 0));
}
}
使用:
<input type="text" appFocus>
您可以简单地使用 scrollIntoView
如下例所示,并随时调用该方法。
<div id="elementID"></div>
ngAfterViewInit(): void
{
const element = document.querySelector("#elementID");
element.scrollIntoView(true);
}
添加你的组件
ngOnInit(): void {
document?.getElementById("elementToGiveFocus")?.focus();
}
我是 Angular 的新手,我正在尝试使用它来将焦点设置在 ID 为 "input1" 的输入上。我正在使用以下代码:
@ViewChild('input1') inputEl: ElementRef;
然后在后面的组件中:
this.inputEl.nativeElement.focus();
但它不起作用。我究竟做错了什么?任何帮助将不胜感激。
组件
import { Component, ElementRef, ViewChild, AfterViewInit} from '@angular/core';
...
@ViewChild('input1', {static: false}) inputEl: ElementRef;
ngAfterViewInit() {
setTimeout(() => this.inputEl.nativeElement.focus());
}
HTML
<input type="text" #input1>
@Z.Bagley提到的问题中的一个答案给了我答案。我必须将 Renderer2 从 @angular/core 导入到我的组件中。那么:
const element = this.renderer.selectRootElement('#input1');
setTimeout(() => element.focus(), 0);
谢谢@MrBlaise 的解决方案!
我也遇到了同样的问题,经过一些搜索我找到了一个很好的解决方案,因为@GreyBeardedGeek 提到 setTimeout 是这个 solution.He 的关键是完全正确的。在您的方法中,您只需添加 setTimeout 即可解决您的问题。
setTimeout(() => this.inputEl.nativeElement.focus(), 0);
这是一个 Angular4+ 指令,您可以在任何组件中 re-use。基于 Niel T 在
import { NgZone, Renderer, Directive, Input } from '@angular/core';
@Directive({
selector: '[focusDirective]'
})
export class FocusDirective {
@Input() cssSelector: string
constructor(
private ngZone: NgZone,
private renderer: Renderer
) { }
ngOnInit() {
console.log(this.cssSelector);
this.ngZone.runOutsideAngular(() => {
setTimeout(() => {
this.renderer.selectRootElement(this.cssSelector).focus();
}, 0);
});
}
}
您可以像这样在组件模板中使用它:
<input id="new-email" focusDirective cssSelector="#new-email"
formControlName="email" placeholder="Email" type="email" email>
给输入一个id并将id传递给指令的cssSelector
属性。或者你可以传递任何你喜欢的 cssSelector。
Niel T 的评论:
Since the only thing I'm doing is setting the focus on an element, I don't need to concern myself with change detection, so I can actually run the call to renderer.selectRootElement outside of Angular. Because I need to give the new sections time to render, the element section is wrapped in a timeout to allow the rendering threads time to catch up before the element selection is attempted. Once all that is setup, I can simply call the element using basic CSS selectors.
这对我有帮助(在离子中,但想法是一样的) https://mhartington.io/post/setting-input-focus/
在模板中:
<ion-item>
<ion-label>Home</ion-label>
<ion-input #input type="text"></ion-input>
</ion-item>
<button (click)="focusInput(input)">Focus</button>
在控制器中:
focusInput(input) {
input.setFocus();
}
这是一个可以在任何组件中使用的指令:
import { NgZone, Directive, ElementRef, AfterContentInit, Renderer2 } from '@angular/core';
@Directive({
selector: '[appFocus]'
})
export class FocusDirective implements AfterContentInit {
constructor(private el: ElementRef, private zone: NgZone, private renderer: Renderer2) {}
ngAfterContentInit() {
this.zone.runOutsideAngular(() => setTimeout(() => {
this.renderer.selectRootElement(this.el.nativeElement).focus();
}, 0));
}
}
使用:
<input type="text" appFocus>
您可以简单地使用 scrollIntoView
如下例所示,并随时调用该方法。
<div id="elementID"></div>
ngAfterViewInit(): void
{
const element = document.querySelector("#elementID");
element.scrollIntoView(true);
}
添加你的组件
ngOnInit(): void {
document?.getElementById("elementToGiveFocus")?.focus();
}