Angular2:自动对焦不适用于视图“刷新"(角度) [英] Angular2: Autofocus does not work on view 'refresh' (angular)
问题描述
我正在构建本质上类似于Duolingo(SPA风格)的QuizTool/LMS.
I'm building a QuizTool/LMS similar in nature to Duolingo (SPA-ish).
tldr:依次单击plnkr,"Check Answers","Do Another",然后注意第一个输入元素不再具有输入焦点-即使"autofocus"属性似乎是正确设置.我可以解决这个问题吗?
tldr: Hit the plnkr, 'Check Answers', 'Do Another', and notice the first input element no longer has the input focus -- even tho the 'autofocus' property seems to be set correctly. Can I fix this?
https://embed.plnkr.co/DU8opUuquP5MXlcfdHIe/
长版:当我第一次进行测验时,我可以将输入焦点(使用绑定的autofocus
属性)设置到屏幕上的第一个输入区域(TEXTAREA,其中用户将回答第一个问题)-这样用户就可以开始打字了.很棒.
long version: When I first render a quiz, I am able to set the input focus (using a bound autofocus
property) into the first input area on the screen (a TEXTAREA where the user will answer the first question) -- so the user can just start typing away. Excellent.
但是,一旦用户提交了第一组问题(第一个测验),用户就可以选择再做一次"测验-I/Angular能够重绘新的测验/UI(目前) ,碰巧是相同的问题),似乎只有'autofocus'属性似乎不起作用-即第一个输入/文本区域没有获得焦点.
However, once the user has submitted that first set of questions (the first quiz), the user can choose to 'Do Another' quiz -- I/Angular am able to redraw a new quiz/UI (with, for now, what happen to be the same exact questions), only the 'autofocus' attribute does not seem to work -- i.e. the first input/textarea does not get the focus.
但是,似乎确实设置了绑定的autofocus
属性.
It does appear that the bound autofocus
attribute is set, however.
这意味着: 1)我以某种方式错误地读取了属性 2)这是Chrome中的错误(Mac OSX上的版本56.0.2924.87(64位)) 3)在正确设置此字段的自动对焦后,某些东西正在获取/窃取焦点 4)等.
Which means either: 1) i'm reading the attribute incorrectly somehow 2) it's a bug in Chrome (Version 56.0.2924.87 (64-bit) on Mac OSX) 3) something is getting/stealing the focus after this field's autofocus is correctly set 4) etc.
我已经在ngFor
循环中设置了"firstQuestion"和"lastQuestion"本地变量,以帮助证明已确定地设置了autofocus属性(只需将[autofocus]="firstQuestion"
更改为[autofocus]="lastQuestion"
).
I've set up 'firstQuestion' and 'lastQuestion' local vars in the ngFor
loop to help prove that the autofocus property is being set deterministically (just change the [autofocus]="firstQuestion"
to [autofocus]="lastQuestion"
).
我愿意解决这个问题,但是我需要这样做.整个没有控制器"的事情对我来说还是很新的,所以很可能我在整个设置中都做得很愚蠢.
I'm open to fixing this however I need to. The whole 'no controller' thing is pretty new to me, so it's very possible I'm doing something stupid with this entire setup.
我尝试使用Angular表单/ngForm,但似乎没有什么作用.
I have tried using Angular forms/ngForm but it doesn't seem to make a difference.
我也很想知道我在哪里可以找到有关Angular2 Transitions/'controller'的基本教程,即如何重绘屏幕或切换到新视图等,而又没有什么可能被视为传统"控制器.我认为您在VB中说过类似的话:
I'd also be curious to know where I could find a basic tutorial on Angular2 transitions/'controller' stuff -- i.e. how do I redraw a screen, or switch to a new view, etc. -- without what might be considered a 'traditional' controller. I think with VB you said something like:
oldForm.hide();
newForm.show();
oldForm.hide();
newForm.show();
如果这些都不起作用,我想手动设置焦点/jqLite/HTML5之前的版本/无论如何-那里都还没有取得很大的成功-因此出现了这个问题.
If none of this works, I want to set the focus manually/jqLite/pre-HTML5/whatever -- haven't had much success there yet either -- thus this question.
谢谢.
不确定它的用处如何,但看来我的应用程序(由ng cli工具设置)与plunkr所产生的内容有显着差异.
Not sure how useful this is, but it seems my app -- which was set up with the ng cli tool -- is different significantly than what plunkr is producing.
我能够发现:
- 即使将'document.activeElement'设置为正确的文本区域(根据查询DOM),对于用户开始输入文本,它仍然可能未被激活(我设置了红色bg使其非常直观)和
-
外部/托管index.html页面(如下所示)在组件加载完成后成为焦点.我添加了一个hack javascript函数,将焦点手动推回到所需的元素上,但这实际上只是用于测试.
- even if the 'document.activeElement' was set to the correct textarea (according to querying the DOM), it might still not be activate for the user to start inputting text (I set a red bg to make it very visual), and
the outer/hosting index.html page, shown below, was getting the focus after my component finished loading. i added a hack javascript function to manually push the focus back to my desired element, but it was really just for testing.
<script>
setInterval(function(){
if(document.activeElement!=null){
if(document.activeElement.id!='textarea-0'){ // find first input element on the page
document.getElementById('textarea-0').focus(); // set the focus
}
}
},
5000);
</script>
更新:
已修复.再次感谢@mickdev.
Fixed. Thanks again to @mickdev.
这是第一个解决方案的小转折.我将其描述为在要呈现的组件上将模板引用变量与ngAfterViewChecked()生命周期方法一起使用".
This is a small twist on the first solution. I'd describe it as "using a template reference variable with the ngAfterViewChecked() lifecycle method on the component you are rendering".
将此内容添加到要渲染的组件中:
Add this stuff to the component you are rendering:
import { ViewChild } from '@angular/core';
@ViewChild('focusThis') focusThis;
// to keep track of which element in our loop we are in
id:number=0
//wait for viewchild to update then focus
ngAfterViewChecked(){
// only focus the 0th (i.e. first) element of our loop
if(this.id == 0){
this.focusThis.nativeElement.focus();
this.id++
}
}
然后添加模板引用变量'#focusThis':
Then add the template reference variable, '#focusThis':
<textarea #focusThis
[(ngModel)]="question.useranswer"
[disabled]="quiz.wasEvaluated"...
推荐答案
这是一个(丑陋的)解决方法,但它可行:) 首先,导入ViewChild
Here is a (ugly) workaround but it works :) First, import ViewChild
import {Component, NgModule, ViewChild} from '@angular/core'
@ViewChild('test') test;
doAnother() {
this.quiz = new Quiz();
this.test.nativeElement.focus();
}
然后更新视图:
<div><textarea [autofocus]="firstQuestion" #test></textarea></div>
这是一个正在工作的unk夫: https://plnkr.co/edit/S6wRn3tUTxZcOQdojzr6?p=preview
Here is a working plunker: https://plnkr.co/edit/S6wRn3tUTxZcOQdojzr6?p=preview
更新:这是实现此ElementRef
//component
import {Component, NgModule, ElementRef} from '@angular/core'
this.element.nativeElement.querySelector('#textarea-1').focus()
//template
<div><textarea id="textarea-{{ question.id }}" [autofocus]="firstQuestion"></textarea></div>
现在,您可以将DOM中的任何文本区域作为目标.这是一个工作的小伙子: https://plnkr.co/edit/izH61uVHBreEwdVQNoSf?p=preview
Now, you can target any textarea in your DOM. Here is a working plunker : https://plnkr.co/edit/izH61uVHBreEwdVQNoSf?p=preview
这篇关于Angular2:自动对焦不适用于视图“刷新"(角度)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!