The keyboard covers the input field in ios - Ionic 5

Viewed 1210

I've been with this same problem for months and I still can't find a solution. I have an application where there are several forms, when focusing on an input field the keyboard covers this input field and the user cannot see anything. This only happens on iOS, on android everything works normal.

In this application I am using ionic 5 with capacitor.

This is how I would like my application to work: EXAMPLE 1

It is currently working like this: EXAMPLE 2

.HTML

<form [formGroup]="formSubmit" (ngSubmit)="formSubmit()">      
  <mat-form-field appearance="outline" class="field-style">
    <input matInput maxlength="35" class="input-form" placeholder="Agregar un alias (opcional)" formControlName="alias">
  </mat-form-field>
  <button mode="ios" class="btn-siguiente-enable" expand="block" type="submit" *ngIf="formSubmit.valid">Siguiente</button>    
</form>

.TS

ngOnInit() {
    this.initForms();

    Plugins.Keyboard.setScroll({isDisabled: true});

    Plugins.Keyboard.addListener('keyboardWillShow', (info: KeyboardInfo) => {
      Plugins.Keyboard.setResizeMode({mode: KeyboardResize.None});
    });

    Plugins.Keyboard.addListener('keyboardWillHide', () => {
      Plugins.Keyboard.setResizeMode({mode: KeyboardResize.Native});
    });
  }  

Any idea how to solve this?

2 Answers

I had this problem too and it was very problematic for my project. So I had three solutions for this

Solution 1 : In your app.component.ts, try forcing the focus on the element clicked like that :

      window.addEventListener('keyboardDidShow', (e) => {
        const elementFocused: any = document.querySelector(':focus');
        if (elementFocused) {
          elementFocused.blur();
          elementFocused.focus();
        }
      });

Adding these lines in the platform.ready method solved my problem for some cases.

Solution 2 : @Eliseo Like he said, adding margin-bottom to simulate the space for the keyboard is also a solution, but if you want to apply it in any input, add it in the app.component.ts using window.addEventListener('keyboardDidShow', (e) => {}); , you can test on keyboardDidShow but also focus event or blur

Solution 3 : Programmatically scroll on click.

I defined my variables like this on my .ts :

@ViewChild('scrollableContent', { static: false }) scrollableContent: ElementRef;
  private scrollContainer: any;

  ngAfterViewInit() {
    this.scrollContainer = this.scrollableContent.nativeElement;
  }
  private scrollToBottom(): void {
    this.scrollContainer.scrollTop = this.scrollContainer.scrollHeight;
  }

And then in my html, i'm doing

<div class="my-scrollable-content" #scrollableContent>
 <input (click)="scrollToBottom()">....</input>  // click event or focus
</div>

Or you can add the listener on your ts like that :

 window.addEventListener('keyboardDidShow', (e) => {
        const elementFocused: any = document.querySelector(':focus');
        if (elementFocused) {
          this.scrollToBottom();
        }
      });

It can sound like a little bit magic but that was the only solutions that worked for my case. The scroll method was the one working the best for me.

why not enclosed your app in a div with, e.g. margin-bottom:300px? this makes that the keyboard has enougth space.

You can also make a directive that is applied to input type text that emit a value to a subject. If your main app listen the value you can get it

export class MarginDirective {
   @HostListener('focus', ['$event.target'])_(){
         this.auxService.marginSubject.next(true)
   }
   @HostListener('blur', ['$event.target'])__(){
         this.auxService.marginSubject.next(false)
   }
   constructor(private auxService:AuxService){}
}

Your service

@Injectable({
  providedIn: 'root',
})
export class AuxService {

  marginSubject:Subject<boolean>=new Subject<boolean>()
  constructor() { }

}

In your main.ts inject the servcie as public

   constructor(public auxService:AuxService){}

And

<router-outlet></router-outlet>
<div *ngIf="auxService.marginSubject|async" style="height:200px">

A fool of all of this in this stackblitz

Related