我有点困惑,试图关注被禁用的输入。我的输入在开始时被禁用。单击按钮后,我想删除禁用attr并关注此输入。
我在焦点this.renderer.removeAttribute(this.elRef.nativeElement, 'disabled');
之前从输入中删除了属性
然后尝试集中输入this.input.nativeElement.focus();
。
this.input
@ViewChild('input') input: ElementRef;
的位置
已禁用属性消失,但输入未聚焦。这是jsfidle
我也尝试绑定到[attr.disabled]
,但它没有帮助。
在Angular中动态关注元素和操纵DOM属性的最佳解决方案是什么?顺便说一句,我正在使用最新的Angular。
答案 0 :(得分:3)
根本不需要渲染器,您只需等待一个滴答,以便更新视图,因此不再禁用nativeElement并且可以集中注意力:
focus() {
this.isDisabled = !this.isDisabled;
setTimeout(() => {
this.input.nativeElement.focus();
});
}
答案 1 :(得分:2)
elRef
是您的主机元素,没有disabled
属性
this.renderer.removeAttribute(this.elRef.nativeElement, 'disabled');
^^^^^
seems input should be here
<强> Plunker Example 强>
为什么在这种情况下输入不集中?我切换了isDisabled - 所以 应该将disabled attr设置为null,我错了吗?那么我们应该能够专注于输入
这是因为角度变化检测机制的工作原理。
只有在没有微任务的情况下,当下一个虚拟机转弯后,它才会被设置为null
但 。 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();
仅检查此组件及其子组件