Having a problem regarding the autofocus attribute in cooperation with Angular. In detail I have a <form> with an <input type="text"> on top which is initially focussed by a condition.

<input [attr.autofocus]="selection===-1"
       [(ngModel)]="myForm.firstInpElem" 
       name="firstInpElem" 
       placeholder="firstInpElem">

This is working as expected (Chrome).

Then the form continuous with a selection between two options controlled by an <input type="radio">.

Once a selection is made an according element is shown and then should get the autofocus.

But that is not happening and I don't understand the reason for it.

Prepared a stackblitz with a working example but mainly below is the markup which won't work as expected

<h1>Forms example</h1>

<form>

  <pre>Condition to focus "firstInpElem" is {{selection===1|json}}</pre>

  <p>This input element is autofocussed on page load</p>

  <p>
    <input [attr.autofocus]="selection===-1"
           [(ngModel)]="myForm.firstInpElem" 
           name="firstInpElem" 
           placeholder="firstInpElem">
  </p>

  <p>
    Provide one of both information:<br>

    <label>
      <input [(ngModel)]="selection" 
             name="radioInpElem"
             type="radio"
             [value]="1"> 
             Option 1
    </label>
    <br>

    <label>
      <input [(ngModel)]="selection" 
             name="radioInpElem"
             type="radio"
             [value]="2">
             Option 2
    </label>

  </p>

  <pre>Condition to focus "secondInpElem" is {{selection===1|json}}</pre>
  <pre>Condition to focus "thirdInpElem" is {{selection===2|json}}</pre>
  <p>


  <input *ngIf="selection===1"
        [attr.autofocus]="selection===1"
        [(ngModel)]="myForm.secondInpElem"
        name="secondInpElem"
        placeholder="secondInpElem">



  <input *ngIf="selection===2"
          [attr.autofocus]="selection===2"
          [(ngModel)]="myForm.thirdInpElem"
          name="thirdInpElem"
          placeholder="thirdInpElem">
  </p>
</form>


<pre>{{myForm|json}}</pre>
up vote 4 down vote accepted

If you check in the development tools (F12 tools), you will see that the new input control actually gets the autofocus attribute, but it does not get the focus. That is because autofocus sets the focus on an element when the page loads. In your case, the page is already loaded when the new element becomes visible.

What you can do instead is to set the focus programmatically on the new input element. In order to do that, you can define a common template reference variable for the two input elements having an ngIf condition:

<input #inputElement *ngIf="selection === 1"
      [(ngModel)]="myForm.secondInpElem"
      name="secondInpElem"
      placeholder="secondInpElem">

<input #inputElement *ngIf="selection === 2"
        [(ngModel)]="myForm.thirdInpElem"
        name="thirdInpElem"
        placeholder="thirdInpElem">

and monitor the presence of these elements with ViewChildren and the QueryList.changes event. Each time one of the input element becomes visible, you set the focus on it:

@ViewChildren("inputElement") inputElements: QueryList<ElementRef>;

ngAfterViewInit() {
  this.inputElements.changes.subscribe(() => {
    this.inputElements.last.nativeElement.focus();
  });
}

See this stackblitz for a demo.

  • Thanks @ConnorsFan this is working perfectly. Didn't knew that autofocus is applied only when page loads – Bernhard Sep 3 at 20:25

Another option is hide the inputs (not use *ngIf else display.style) and reference variables see https://stackblitz.com/edit/angular-sbc4pp?file=src%2Fapp%2Fapp.component.html

    <label>
      <input [ngModel]="selection" (change)="change(second,1)" 
             name="radioInpElem"
             type="radio"
             [value]="1"> 
             Option 1
    </label>
    <br>
    <label>
      <input [ngModel]="selection" (change)="change(third,2)"
             name="radioInpElem"
             type="radio"
             [value]="2">
             Option 2
    </label>

  <input #second [style.display]="selection===1?'inherit':'none'"
        [(ngModel)]="myForm.secondInpElem"
        name="secondInpElem"
        placeholder="secondInpElem">

  <input #third [style.display]="selection===2?'inherit':'none'"
          [(ngModel)]="myForm.thirdInpElem"
          name="thirdInpElem"
          placeholder="thirdInpElem">

Your function change like

  change(element:any,index:number)
  {
  this.selection=index;
  setTimeout(()=>{element.focus()},0);
  }

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.