3

In my PWA built with Ionic and Angular 8, I am in need to handle enter key press to move to next element. How can I achieve it with (keyup.enter). Please help me.

https://stackblitz.com/edit/ionic-3drfby

web developer
  • 457
  • 2
  • 10
  • 25
  • 1
    Please add the relevant code as code blocks. This question would become completely useless if (when) the link dies. A Stackblitz is awesome!! :) but questioin **itself** should provide a [mcve] – AT82 Nov 21 '19 at 08:32

2 Answers2

6

I would write a custom directive for this. Insipired by this answer. The directive could be placed on the formtag, we use HostListener to listen to keyup.enter and if a next element exist, we move the focus to it.

We would need to make some changes on how your form is submitted, since ngSubmit would be called each time you press enter. So I would remove that from the form tag, set the button to type="button" and instead attach click event to it to call logForm().

So all in all this is what I do:

<form focusDir>
<!-- .... -->
<button ion-button type="button" block (click)="logForm()">Add Todo</button>

The directive:

@Directive({
  selector: "[focusDir]"
})
export class FocusDirective {
  constructor() {}

  @HostListener("keyup.enter") onKeyupEnter() {
    var nextEl = this.findNextTabStop(document.activeElement);
    nextEl.focus();
    // or try for ionic 4:
    // nextEl.setFocus();
  }

  findNextTabStop(el) {
    var universe = document.querySelectorAll(
      "input, button, select, textarea, a[href]"
    );
    var list = Array.prototype.filter.call(universe, function(item) {
      return item.tabIndex >= "0";
    });
    var index = list.indexOf(el);
    return list[index + 1] || list[0];
  }
}

Then mark this directive in the declarations array in your ngModule.

STACKBLIZ

AT82
  • 71,416
  • 24
  • 140
  • 167
5

one way is to setting a reference of the next element. like below

<ion-content padding>
 <form (ngSubmit)="logForm()">
      <ion-item>
        <ion-label>Todo1</ion-label>
        <ion-input type="text" [(ngModel)]="todo.title1" name="title1" #a (keyup.enter)="setFocus(b)"></ion-input>
      </ion-item>
      <ion-item>
        <ion-label>Todo2</ion-label>
        <ion-input type="text" [(ngModel)]="todo.title2" name="title2" #b (keyup.enter)="setFocus(c)"></ion-input>
      </ion-item>
      <ion-item>
        <ion-label>Todo3</ion-label>
        <ion-input type="text" [(ngModel)]="todo.title3" name="title3" #c (keyup.enter)="setFocus(d)"></ion-input>
      </ion-item>
      <ion-item>
        <ion-label>Description</ion-label>
        <ion-textarea [(ngModel)]="todo.description" name="description" #d></ion-textarea>
      </ion-item>
      <button ion-button type="submit" block>Add Todo</button>
    </form>
</ion-content>

and in .ts file

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
todo = {}
  logForm() {
    console.log(this.todo)
  }

  setFocus(nextElement) {
     nextElement.setFocus(); //For Ionic 4
    //nextElement.focus(); //older version
  }

  constructor(public navCtrl: NavController) {

  }

}
suresh bambhaniya
  • 1,687
  • 1
  • 10
  • 20
  • 1
    Thanks, this works for elements ion-input/textarea etc. When you are using basic input elements, even in ionic 4+ it's necessary to use the older way nextElement.focus(). I resolved that by using try/catch statement, and when an error happens, I called the next Element.focus(); – Najib El Alam Nov 08 '21 at 13:29