如何使用Angular4按元素id设置焦点

Pis*_*ity 24 angular angular-forms

我是Angular的新手,我正在尝试使用它来设置id为"input1"的输入.我使用以下代码:

@ViewChild('input1') inputEl: ElementRef;
Run Code Online (Sandbox Code Playgroud)

然后在组件中:

 this.inputEl.nativeElement.focus();
Run Code Online (Sandbox Code Playgroud)

但它没有用.我究竟做错了什么?任何帮助都感激不尽.

Dmi*_*nko 42

零件

import { Component, ElementRef, ViewChild, AfterViewInit} from '@angular/core';
... 

@ViewChild('input1') inputEl:ElementRef;

ngAfterViewInit() {
      setTimeout(() => this.inputEl.nativeElement.focus());
}
Run Code Online (Sandbox Code Playgroud)

HTML

<input type="text" #input1>
Run Code Online (Sandbox Code Playgroud)

  • @ANeves Stijn Van Bael 添加了 `setTimeout()` 以防止 `ExpressionChangedAfterItHasBeenCheckedError` (2认同)

Pis*_*ity 19

@ Z.Bagley提到的问题中的一个答案给了我答案.我不得不将@ angular/core中的Renderer2导入到我的组件中.然后:

const element = this.renderer.selectRootElement('#input1');

// setTimeout(() => element.focus, 0);
setTimeout(() => element.focus(), 0);
Run Code Online (Sandbox Code Playgroud)

谢谢@MrBlaise的解决方案!

  • setTimeout是这里的关键.您还可以通过使用ViewChild批注对ElementRef属性进行批注,然后引用该ElementRef的'nativeElement'属性来获取不带渲染器的元素. (6认同)

Abh*_*eet 7

经过一番搜索,我也遇到了同样的问题,我找到了一个很好的解决方案,因为@GreyBeardedGeek 提到 setTimeout 是这个解决方案的关键。他是完全正确的。在您的方法中,您只需要添加 setTimeout 即可解决您的问题。

setTimeout(() => this.inputEl.nativeElement.focus(), 0);
Run Code Online (Sandbox Code Playgroud)


rmc*_*rry 5

这是一个 Angular4+ 指令,您可以在任何组件中重用它。基于 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);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在组件模板中使用它,如下所示:

<input id="new-email" focusDirective cssSelector="#new-email"
  formControlName="email" placeholder="Email" type="email" email>
Run Code Online (Sandbox Code Playgroud)

为输入提供一个 id 并将该 id 传递给cssSelector指令的属性。或者你可以传递任何你喜欢的 cssSelector。

来自 Niel T 的评论:

因为我唯一要做的就是将焦点设置在一个元素上,所以我不需要关心变化检测,所以我实际上可以在 Angular 之外运行对 renderer.selectRootElement 的调用。因为我需要给新部分时间来渲染,元素部分被包裹在超时中,以允许渲染线程在尝试选择元素之前赶上时间。完成所有设置后,我可以使用基本的 CSS 选择器简单地调用元素。