【发布时间】:2019-10-21 22:53:25
【问题描述】:
在 Angular2 中,我如何设置元素焦点的绑定。 我不想用 elementRef 设置它。 我认为在 AngularJS 中有 ngFocus 指令 在 Angular2 中没有这样的指令
【问题讨论】:
标签: angular
在 Angular2 中,我如何设置元素焦点的绑定。 我不想用 elementRef 设置它。 我认为在 AngularJS 中有 ngFocus 指令 在 Angular2 中没有这样的指令
【问题讨论】:
标签: angular
渲染器服务现在是 deprecated(从 Angular 4.x 开始) 新的 Renderer2 服务没有 invokeElementMethod。 您可以做的是获取对元素的引用,如下所示:
const element = this.renderer.selectRootElement('#elementId');
然后你可以像这样使用它来关注那个元素:
element.focus();
更多关于selectRootElement如何工作here:
编辑:
如果元素没有获得焦点,常见的问题是元素还没有准备好。 (例如:禁用、隐藏等)。你可以这样做:
setTimeout(() => element.focus(), 0);
这将创建一个将在下一个 VM 轮次中运行的宏任务,因此如果您启用该元素,焦点将正常运行。
【讨论】:
一个简单的“焦点”指令
import {Directive, Input, ElementRef} from 'angular2/core';
@Directive({
selector: '[focus]'
})
class FocusDirective {
@Input()
focus:boolean;
constructor(@Inject(ElementRef) private element: ElementRef) {}
protected ngOnChanges() {
this.element.nativeElement.focus();
}
}
// Usage
@Component({
selector : 'app',
template : `
<input [focus]="inputFocused" type="text">
<button (click)="moveFocus()">Move Focus</button>
`,
directives: [FocusDirective]
})
export class App {
private inputFocused = false;
moveFocus() {
this.inputFocused = true;
// we need this because nothing will
// happens on next method call,
// ngOnChanges in directive is only called if value is changed,
// so we have to reset this value in async way,
// this is ugly but works
setTimeout(() => {this.inputFocused = false});
}
}
【讨论】:
nativeElement。这不与网络工作者一起保存。
directives 属性已在 RC 6 中删除。您应该将 FocusDirective 移动到 NgModule 装饰器的声明属性中。
我尝试了两种变体,但没有一个适合简单使用。第一个(@AngJobs)需要在您使用指令(设置焦点 = true)的组件中进行额外的工作,第二个(@ShellZero)根本不工作,因为在视图实际准备好之前调用焦点。所以我将焦点呼叫转移到ngAfterViewInit。现在您可以添加<input focus... 并忘记它。元素会在视图初始化后自动获得焦点。
import { Directive, ElementRef, Renderer, AfterViewInit } from '@angular/core';
@Directive({
selector: '[focus]'
})
export class DmFocusDirective implements AfterViewInit {
constructor(private _el: ElementRef, private renderer: Renderer) {
}
ngAfterViewInit() {
this.renderer.invokeElementMethod(this._el.nativeElement, 'focus');
}
}
【讨论】:
Dm 所做的那样)。应用前缀的关键位是选择器名称值。即selector: '[appFocus]'。我想这会减少后续角度版本等中发生冲突的可能性。
Renderer 已被弃用,Angular 团队不打算将 invokeElementMethod() 转发到 Renderer2。 github.com/angular/angular/issues/13818
来自@MrBlaise,我使用了 setTimeout sn-p,它为我完成了以下工作。
<input type="text" #searchInput />
import { ElementRef, ViewChild } from '@angular/core';
...
@ViewChild('searchInput') private searchInput: ElementRef;
...
setTimeout(() => this.searchInput.nativeElement.focus(), 0);
【讨论】:
使用 angular2 将焦点设置在元素上的最佳方法是使用 Renderer 并调用元素上的方法。没有elementRef,就无法做到这一点。
结果如下:
this.renderer.invokeElementMethod(this.input.nativeElement, 'focus', []);
renderer 使用 protected renderer : Renderer 注入到构造函数中
【讨论】:
更简单的方法:
import { Directive, ElementRef, Renderer} from "@angular/core";
@Directive({
selector: "[Focus]"
})
export class myFocus {
constructor(private _el: ElementRef, private renderer: Renderer) {
this.renderer.invokeElementMethod(this._el.nativeElement, 'focus');
}
}
【讨论】:
它对我有用,但在控制台中有错误。 经过调试和搜索发现这篇文章:https://www.picnet.com.au/blogs/guido/post/2016/09/20/angular2-ng2-focus-directive/
只需复制粘贴即可。它对我来说非常有效。
import {Directive, AfterViewInit, ElementRef, DoCheck} from '@angular/core';
@Directive({selector: '[focus]'})
export class FocusDirective implements AfterViewInit, DoCheck {
private lastVisible: boolean = false;
private initialised: boolean = false;
constructor(private el: ElementRef) {
}
ngAfterViewInit() {
console.log('inside FocusDirective.ngAfterViewInit()');
this.initialised = true;
this.ngDoCheck();
}
ngDoCheck() {
console.log('inside FocusDirective.ngDoCheck()');
if (!this.initialised) {
return;
}
const visible = !!this.el.nativeElement.offsetParent;
if (visible && !this.lastVisible) {
setTimeout(() => {
this.el.nativeElement.focus();
}, 1);
}
this.lastVisible = visible;
}
}
【讨论】:
import { Directive, ElementRef, AfterViewChecked } from '@angular/core';
@Directive({
selector: '[autoFocus]',
})
export class FocusDirective implements AfterViewChecked {
constructor(private _elementRef: ElementRef) { }
ngAfterViewChecked() {
this._elementRef.nativeElement.focus()
}
}
【讨论】:
诀窍是同时使用焦点和选择:
this.(element).nativeElement.focus();
this.(element).nativeElement.select();
【讨论】: