I'm building a QuizTool/LMS similar in nature to Duolingo (SPA-ish).
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/
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.
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.
It does appear that the bound autofocus
attribute is set, however.
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.
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.
I have tried using Angular forms/ngForm but it doesn't seem to make a difference.
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();
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.
Thank you.
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.
i was able to discover that:
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>
Update:
Fixed. Thanks again to @mickdev.
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++
}
}
Then add the template reference variable, '#focusThis':
<textarea #focusThis
[(ngModel)]="question.useranswer"
[disabled]="quiz.wasEvaluated"...
This will work only on page navigation (if you are lucky). Here's my take on Angular autofocus directive. The following directive accepts boolean value as an input and focuses the element based on the evaluated boolean expression so the element could be focused dynamically.
Make It Easy: Angular auto focus for input box - Angular. 1 1. Auto focus on textbox using directive. Especially while dealing with forms you may need to set default focus on some fields. We are going to create ... 2 2. Set focus on text box on click. 3 3. Auto focus on textbox without using a directive.
We will look at the best method to do a page refresh on Angular. First, we will have to head to our editor, open the terminal most preferably Visual Studio Code and create the app-routing.module.ts using the ng generate function.
We target each element with the autofocus attribute, and explicitly invoke the focus () method in its ngAfterViewInit hook. We can also take it one step further, and expose an input that will focus the element based on its value.
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();
}
Then update the view :
<div><textarea [autofocus]="firstQuestion" #test></textarea></div>
Here is a working plunker: https://plnkr.co/edit/S6wRn3tUTxZcOQdojzr6?p=preview
Update: here is a more elegant way to achieve this 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>
Now, you can target any textarea in your DOM. Here is a working plunker : https://plnkr.co/edit/izH61uVHBreEwdVQNoSf?p=preview
<input type="text" #myInput />
{{ myInput.focus() }}
Just add {{ myInput.focus() }} right after input inside template
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With