Angular2:自动对焦在视图'刷新'(角度)

时间:2017-03-09 12:23:58

标签: angular

我正在构建一个类似于Duolingo(SPA-ish)的QuizTool / LMS。

tldr:点击plnkr,'检查答案','做另一个',并注意第一个输入元素不再具有输入焦点 - 即使'自动对焦'属性似乎是设置正确。我能解决这个问题吗?

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

长版本:当我第一次渲染测验时,我能够将输入焦点(使用绑定的autofocus属性)设置到屏幕的第一个输入区域(TEXTAREA用户将回答第一个问题) - 因此用户可以开始输入。优异。

然而,一旦用户提交了第一组问题(第一个测验),用户就可以选择“做另一个”测验 - 我/ Angular能够重新绘制新的测验/用户界面(现在, ,恰好是相同的问题),只有'自动对焦'属性似乎不起作用 - 即第一个输入/ textarea没有得到焦点。

但是,似乎设置了绑定的autofocus属性。

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

我在ngFor循环中设置了'firstQuestion'和'lastQuestion'本地变量,以帮助证明自动对焦属性是确定性设置的(只需将[autofocus]="firstQuestion"更改为{{1} })。

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

我尝试过使用Angular forms / ngForm,但它似乎没什么区别。

我也很想知道在哪里可以找到关于Angular2过渡/'控制器'的基本教程 - 即如何重绘屏幕,或切换到新视图等等 - 没有什么可能被视为“传统”控制者。我认为用VB你会说:

[autofocus]="lastQuestion"

如果这一切都不起作用,我想手动设置焦点/ jqLit​​e / pre-HTML5 /无论如何还没有取得多少成功 - 因此这个问题。

谢谢。

不确定这是多么有用,但似乎我的应用程序 - 使用ng cli工具设置 - 与plunkr正在生成的有很大不同。

我能够发现:

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

    oldForm.hide();
    newForm.show();
  3. 更新

    固定。再次感谢@mickdev。

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

    将此内容添加到您要呈现的组件中:

    <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>
    

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

    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++
        }
    }
    

2 个答案:

答案 0 :(得分:2)

这是一个(丑陋的)解决方法,但它有效:) 首先,导入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>

这是一个工作的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中的任何textarea。这是一个工作的plunker: https://plnkr.co/edit/izH61uVHBreEwdVQNoSf?p=preview

答案 1 :(得分:1)

<input type="text" #myInput />
{{ myInput.focus() }}

在模板

中输入后立即添加{{myInput.focus()}}