Angular2:自动对焦不适用于“刷新”视图(角度)

Pet*_*ith 6 angular

我正在构建本质上类似于Duolingo(SPA风格)的QuizTool / LMS。

tldr:依次单击plnkr,“ Check Answers”,“ Do Another”,然后注意第一个输入元素不再具有输入焦点-即使“ autofocus”属性似乎设置正确。我可以解决这个问题吗?

https://embed.plnkr.co/DU8opUuquP5MXlcfdHIe/

加长版:当我第一次进行测验时,我可以将输入焦点(使用绑定autofocus属性)设置到屏幕上的第一个输入区域(一个TEXTAREA,用户将在其中回答第一个问题)-这样用户可以刚开始打字。优秀。

但是,一旦用户提交了第一组问题(第一个测验),用户就可以选择“再做一次”测验-I / Angular能够重绘新的测验/ UI(到目前为止,发生了什么情况) (完全相同的问题),只有'autofocus'属性似乎不起作用-即第一个输入/文本区域没有获得焦点。

看来autofocus确实设置了bound 属性。

这意味着:1)我以某种方式错误地读取了属性2)它是Chrome中的错误(Mac OSX上的版本56.0.2924.87(64位))3)在此字段的自动对焦正确后,某些东西正在获取/窃取焦点设置4)等

我在ngFor循环中设置了“ firstQuestion”和“ lastQuestion”本地变量,以帮助证明已确定地设置了autofocus属性(只需将更[autofocus]="firstQuestion"改为[autofocus]="lastQuestion")。

我愿意解决此问题,但我需要这样做。整个“无控制器”的东西对我来说还是很新的,因此很可能我在整个设置中都做了一些愚蠢的事情。

我尝试使用Angular表单/ ngForm,但似乎没有什么不同。

我也很想知道我在哪里可以找到有关Angular2 Transitions /'controller'的基本教程,即如何重绘屏幕或切换到新视图等,而又没有发现什么呢? “传统”控制器。我认为使用VB时您会说:

oldForm.hide(); newForm.show();

如果这些都不起作用,我想手动设置焦点/ jqLit​​e / HTML5之前的版本/无论如何-那里都还没有取得很大的成功-因此出现了这个问题。

谢谢。


不确定这有什么用处,但似乎我的应用程序(由ng cli工具设置)与plunkr产生的应用程序有很大不同。

我发现了:

  1. 即使'document.activeElement'设置为正确的文本区域(根据查询DOM),对于用户开始输入文本,它仍然可能未被激活(我设置了红色bg使其非常直观),并且
  2. 组件加载完成后,外部/托管index.html页(如下所示)成为焦点。我添加了一个hack javascript函数,将焦点手动推回所需的元素,但这实际上只是用于测试。

    <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>
    
    Run Code Online (Sandbox Code Playgroud)

更新:

固定。再次感谢@mickdev。

这是第一个解决方案的小转折。我将其描述为“在要呈现的组件上将模板引用变量与ngAfterViewChecked()生命周期方法一起使用”。


将此东西添加到要渲染的组件中:

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++
    }
}
Run Code Online (Sandbox Code Playgroud)

然后添加模板引用变量“ #focusThis”:

<textarea   #focusThis
            [(ngModel)]="question.useranswer" 
            [disabled]="quiz.wasEvaluated"...
Run Code Online (Sandbox Code Playgroud)

mic*_*dev 4

这是一个(丑陋的)解决方法,但它有效:)首先,导入 ViewChild

import {Component, NgModule, ViewChild} from '@angular/core'

@ViewChild('test') test;

doAnother() {
    this.quiz = new Quiz();

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

然后更新视图:

<div><textarea [autofocus]="firstQuestion" #test></textarea></div>
Run Code Online (Sandbox Code Playgroud)

这是一个工作插件: 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>
Run Code Online (Sandbox Code Playgroud)

现在,您可以定位 DOM 中的任何文本区域。这是一个工作插件: https://plnkr.co/edit/izH61uVHBreEwdVQNoSf ?p=preview