Setting Focus to an Input in Ionic

I found this possible solution:

.html

<ion-content>
  <ion-list>
    <ion-item>
      <ion-label>Name</ion-label>
      <ion-input #inputRef type="text"></ion-input>
    </ion-item>
    <button ion-button (click)="focusMyInput(inputRef)">Focus</button>
  </ion-list>
</ion-content>

.ts

import {Content} from 'ionic-angular';

@ViewChild(Content) content: Content;

  focusMyInput(inputRef) {

    let itemTop = inputRef._elementRef.nativeElement.getBoundingClientRect().top;
    let itemPositionY = this.content.getContentDimensions().scrollTop + itemTop -80;
   
    this.content.scrollTo(null, itemPositionY, 500, () => {
      inputRef.setFocus();
    });

  }

But you have to make sure you have enough space to scroll at bottom. Tested on iOS 11

1 Like

Content is not defined error

Make sure to “import {Content} from ‘ionic-angular’;” at the top of your .ts file. And of course your content musst be placed between tags.

I’ve edited my post.

1 Like

In my case, for some reason, ionViewLoaded() was not getting triggered. Tried ionViewDidLoad() and set the timer to 200 and it worked.

150 proved too early for me. Complete Solution:

import { Component, ViewChild } from '@angular/core';//No need to import Input

export class HomePage {

  @ViewChild('inputToFocus') inputToFocus;
  constructor(public navCtrl: NavController) {}

  ionViewDidLoad()
  {
    setTimeout(() => {
      this.inputToFocus.setFocus();
    },200)
  }  
}

And on the input tag:

<ion-input type="text" #inputToFocus></ion-input>

2 Likes

The best solution. Works great for me too! =) But in my case I used set.Blur() method for my own purposes.

1 Like

I found a solution as a Directive

import { Directive, Renderer, ElementRef} from '@angular/core';
 
@Directive({ 
    selector: '[focuser]' // Attribute selector
})
export class Focuser {

    constructor(private renderer:Renderer,
                private elementRef:ElementRef) {
    }

    ngAfterViewInit() { 
        // we need to delay our call in order to work with ionic ...
        setTimeout(() => {
            const element = this.elementRef.nativeElement.querySelector('input');
            this.renderer.invokeElementMethod(element, 'focus', []);
        }, 1000);
    }   
}

add to app.module

import { Focuser } from "../directives/focuser/focuser";

@NgModule({
  declarations: [ ... 
                         Focuser  ]

use the directive.

<ion-input focuser . . . >

1 Like

Does it work in mobile iOS safari?

Make sure to upload : cordova-plugin-ionic-webview

Hey Blaydator,
I am having the same issue here and couldn’t make input field focus on iPhone (Keyboard doesn’t appear too). Do you have a solution on this?

Mine is a little different.
On ios 10,
Using the old webkit
preference name=“CordovaWebViewEngine” value=“CDVUIWebViewEngine”

Trying to do a wizard in a modal. After a couple of screens we have a form for the users address. What is strange on iphone 7 with ios 10 the zip code (last value in the from) is what gets focused.

How can I change that to get focus on the first input?

I found that the solution provided by alchibaucha works, but I had to significantly increase the delay. So mine now works when it’s set to 600.

import { Component, ViewChild } from '@angular/core';//No need to import Input

export class HomePage {

  @ViewChild('inputToFocus') inputToFocus;
  constructor(public navCtrl: NavController) {}

  ionViewDidLoad()
  {
    setTimeout(() => {
      this.inputToFocus.setFocus();
    },600)
  }  
}

Have you tried a using it in ionViewDidEnter lifecycle hook instead of ionViewDidLoad - works for me

I find if I put it in a ionViewDidLoad the keyboard disappears and UX is broken,

what I’ve found works (on device) is to put the a ionViewDidEnter lifecycle hook

ionViewDidEnter()
  {
    setTimeout(() => {
      this.inputToFocus.setFocus();
    },200)
  }  

I had this problem too until I used the ionViewDidEnter lifecycle hook

ionViewDidEnter()
  {
    setTimeout(() => {
      this.inputToFocus.setFocus();
    },200)
  }  
2 Likes

Use index for generating IDs

*ngFor=“let phoneInput of phoneInputList; let i = index”

when you have unique id for input create function:

setTimeout(() => {
const inputFieldIDElement = document.getElementById(“InputFieldID” + index);
if (inputFieldIDElement) {
const inputTagCollection = inputFieldIDElement.getElementsByTagName(“input”);
if (inputTagCollection && inputTagCollection.item(0)) {
const inputElement = inputTagCollection.item(0);
inputElement.focus();
}
}
}, 300);

1 Like

I think this will be helpful

  1. Add reference into the template
    <input #inputEl>

  2. Import ViewChild on the top of .ts and define a reference variable in class

     import { ViewChild } from '@angular/core';
      ...
     @ViewChild('inputEl') inputElRef;
    
  3. Use nativeElement to access focus() function
    this.inputElRef.nativeElement.focus();

2 Likes

Use ngAfterViewChecked() Angular hook and execute .setFocus() inside it.

While working with the Ionic 3 Framework I came across (as it turns out) popular problem of autofocusing an input after showing a component on the page.

The most popular answer to this problem advises to use setTimeout

ionViewLoaded() {
    setTimeout(() => {
        this.myInput.setFocus();
    },150);
}

I hate such workarounds so I’ve decided to dig deeper. While none of the available Ionic lifecycle hooks works, in that case, there are also Angular lifecycle hooks. It turns out that ngAfterViewChecked is the one I was looking for:

ngAfterViewChecked() {
    this.myInput.setFocus()
}

So that is clean setFocus() solution for Ionic without using setTimeout() workaround.

refer to the input element with this.myInput you have to define it inside your Component as a ViewChild.

Here is the example of Modal Component which will autofocus its input after showing itself on the page.
Javascript:

@Component({
  selector: 'my-modal',
  templateUrl: 'my-modal.html',
})
export class MyModal {

  @ViewChild('myInput') myInput;

  constructor( ) { }

  ngAfterViewChecked() {
    this.myInput.setFocus()
  }

  dismiss() {
    this.viewCtrl.dismiss();
  }
}

If you need to set focus on an input at init component, set the class input-has-focus by default to ion-item just like this:

<ion-item class="input-has-focus">

That’s all!

1 Like

what are the properties inside the “input-has-focus” class.

Hi! I tried this solution and it works fine: the input focuses when the component is loaded, but then the keyboard cannot be closed afterwards. Whenever I try to hide it, it pops up again. Is there a way of solving this?

I tried ngAfterViewInit() insead of ngAfterViewChecked(), because this way it should be called only once. But in this case, when the component loads, the input is focused (and keyboard appears) only for a second, then keyboard closes back again and the field is no longer focused. I don´t know why, seems like something else is resetting the setFocus command.

Any ideas?