我有点困惑,试图集中禁用的输入。我的输入在开始时被禁用。单击按钮后,我想删除禁用attr并关注此输入。
我在焦点this.renderer.removeAttribute(this.elRef.nativeElement, 'disabled');
之前从输入中删除了属性,然后尝试将焦点输入this.input.nativeElement.focus();
。
其中this.input
是@ViewChild('input') input: ElementRef;
禁用属性消失,但输入没有集中。这是jsfidle我也尝试绑定到[attr.disabled]
,但它没有帮助。
什么是动态关注元素和操纵Angular中DOM属性的最佳解决方案?顺便说一句,我正在使用最新的Angular。
elRef
是你没有disabled
属性的宿主元素
this.renderer.removeAttribute(this.elRef.nativeElement, 'disabled');
^^^^^
seems input should be here
为什么在这种情况下输入不集中?我切换isDisabled - 所以禁用attr应设置为null,我错了吗?那么我们应该能够专注于输入
那是因为角度变化检测机制的工作原理。
它将被设置为null
但仅在没有微任务的情况下在下一个VM转向之后。 Angular使用zone.js来运行更改检测。
this.isDisabled = !this.isDisabled; // 1) you only change property
this.input.nativeElement.focus(); // 2) you executed focus(input is still disabled)
....
....
AppRef
zone.onMicrotaskEmpty.subcribe(() => run change detection) // 3) your template is updated
您有几种方法可以解决此问题:
1)使用Renderer2
API,如答案开头所示
2)订阅onMicrotaskEmpty
事件Example
import { take } from 'rxjs/operators/take';
constructor(private zone: NgZone) {}
focus() {
this.isDisabled = !this.isDisabled;
this.zone.onMicrotaskEmpty.pipe(
take(1)
).subscribe(() => {
this.input.nativeElement.focus();
});
}
在这种情况下,角度应用程序不会调用添加更改检测周期。
3)使用setTimeout
,如另一个答案所示。
您的角度应用程序还将检查完整的组件树。
4)在另一个答案的评论中建议使用ChangeDetectorRef.detectChanges()
方法。
this.isDisabled = !this.isDisabled;
this.cdRef.detectChanges();
this.input.nativeElement.focus();
额外检查此组件及其子组件
根本不需要渲染器,您只需要等待一个滴答,以便更新视图,因此不再禁用nativeElement并且可以集中注意力:
focus() {
this.isDisabled = !this.isDisabled;
setTimeout(() => {
this.input.nativeElement.focus();
});
}