Skip to content

Instantly share code, notes, and snippets.

@Manduro
Last active August 24, 2020 06:50
Show Gist options
  • Star 53 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save Manduro/bc121fd39f21558df2a952b39e907754 to your computer and use it in GitHub Desktop.
Save Manduro/bc121fd39f21558df2a952b39e907754 to your computer and use it in GitHub Desktop.
Ionic Keyboard Attach Directive
import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
import { Keyboard } from '@ionic-native/keyboard';
import { Content, Platform } from 'ionic-angular';
import { Subscription } from 'rxjs/Subscription';
/**
* @name KeyboardAttachDirective
* @source https://gist.github.com/Manduro/bc121fd39f21558df2a952b39e907754
* @description
* The `keyboardAttach` directive will cause an element to float above the
* keyboard when the keyboard shows. Currently only supports the `ion-footer` element.
*
* ### Notes
* - This directive requires [Ionic Native](https://github.com/driftyco/ionic-native)
* and the [Ionic Keyboard Plugin](https://github.com/driftyco/ionic-plugin-keyboard).
* - Currently only tested to work on iOS.
* - If there is an input in your footer, you will need to set
* `Keyboard.disableScroll(true)`.
*
* @usage
*
* ```html
* <ion-content #content>
* </ion-content>
*
* <ion-footer [keyboardAttach]="content">
* <ion-toolbar>
* <ion-item>
* <ion-input></ion-input>
* </ion-item>
* </ion-toolbar>
* </ion-footer>
* ```
*/
@Directive({
selector: '[keyboardAttach]'
})
export class KeyboardAttachDirective implements OnInit, OnDestroy {
@Input('keyboardAttach') content: Content;
private onShowSubscription: Subscription;
private onHideSubscription: Subscription;
constructor(
private elementRef: ElementRef,
private keyboard: Keyboard,
private platform: Platform
) {}
ngOnInit() {
if (this.platform.is('cordova') && this.platform.is('ios')) {
this.onShowSubscription = this.keyboard.onKeyboardShow().subscribe(e => this.onShow(e));
this.onHideSubscription = this.keyboard.onKeyboardHide().subscribe(() => this.onHide());
}
}
ngOnDestroy() {
if (this.onShowSubscription) {
this.onShowSubscription.unsubscribe();
}
if (this.onHideSubscription) {
this.onHideSubscription.unsubscribe();
}
}
private onShow(e) {
let keyboardHeight: number = e.keyboardHeight || (e.detail && e.detail.keyboardHeight);
this.setElementPosition(keyboardHeight);
};
private onHide() {
this.setElementPosition(0);
};
private setElementPosition(pixels: number) {
this.elementRef.nativeElement.style.paddingBottom = pixels + 'px';
this.content.resize();
}
}
@maitham
Copy link

maitham commented May 10, 2017

Is there anyway of getting the footer to slowly come up, i.e. add a transition rather than instantly moving position to accomodate the keyboard?

@jsmithangular
Copy link

@Manduro? how can I use this directive? I want to know the step by step tutorial

@YasirSherzad
Copy link

hi , I have a problem with the returned keyboardHeight value, it returns a large height causing the footer to be pushed way up. I am using ionic 3 and testing this on android, any advice, thanx.

@harshalkalavadiya-star
Copy link

harshalkalavadiya-star commented Jul 21, 2017

Hello guys i use above code and i call in my html page as below

<ion-content padding #content>
Name (*)
<ion-input #txtGroupName type="text" [(ngModel)]="client.name">

<ion-footer no-padding no-margin class="custom-footer" [keyboardAttach]="content">
<button ion-button full no-padding no-margin (click)="onClickAddClientContact()">CREATE

When i run my code i get error message like below
error

@peterprice
Copy link

@Harshal111 Add keyboard provider in app.module.ts:

//...
import { Keyboard } from '@ionic-native/keyboard';
//...
  providers: [
    Keyboard,
//...

@rdlabo
Copy link

rdlabo commented Sep 12, 2017

I suggest controll scroll with onShow, when keyboard open.

    private onShow(e) {
        let keyboardHeight: number = e.keyboardHeight || (e.detail && e.detail.keyboardHeight);
        this.setElementPosition(keyboardHeight);

        setTimeout(()=>{
            window.scrollTo(0, 0) ;
            this.content.scrollToBottom(0);
            this.keyboard.disableScroll(true);
        });
    };

thanks.

@CK110
Copy link

CK110 commented Oct 20, 2017

it‘work,but the scollcontent is to large

@pingu1m
Copy link

pingu1m commented Oct 31, 2017

+1 Worked for me.

@rdlabo
Copy link

rdlabo commented Dec 12, 2017

I wrote keyboard attach directive for iOS 11.
https://gist.github.com/rdlabo/57bb9a2098f2f83c2c1cc16c8e88f6d5

please reference.

@JacoRoos
Copy link

Well done dude. Tested this on Android on Ionic 3 and it works as well. You just need to remove the platform check for iOS if using it on Android.

@piraveen
Copy link

piraveen commented Mar 9, 2018

Works great on iOS 11.2 👍 Thanks 😃

@WolffDev
Copy link

WolffDev commented Mar 26, 2018

This works on android as well, if you just add the following to the directive. Why is it not already in there?

ngOnInit() {
  if (this.platform.is('cordova') && this.platform.is('ios') || this.platform.is('android')) {
    this.onShowSubscription = this.keyboard.onKeyboardShow().subscribe(e => this.onShow(e));
    this.onHideSubscription = this.keyboard.onKeyboardHide().subscribe(() => this.onHide());
  }
}

Notices the || this.platform.is('android')

@ejerskov
Copy link

ejerskov commented May 30, 2018

I've added the directive to app.module:

@NgModule({ declarations: [ MyApp, GroceryListMorePage, KeyboardAttachDirective ],

But I keep getting this error. Anyone who has a hint?

Can't bind to 'keyboardAttach' since it isn't a known property of 'ion-footer'.
1. If 'ion-footer' is an Angular component and it has 'keyboardAttach' input, then verify that it is part of this module.
2. If 'ion-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
    </ion-list>
</ion-content>
<ion-footer [ERROR ->][keyboardAttach]="content">
    <ion-toolbar>
        <ion-item>
")

My HTML:

<ion-content #content>
    ...
</ion-content>
<ion-footer [keyboardAttach]="content">
    <ion-toolbar>
        <ion-item>
            <ion-input></ion-input>
        </ion-item>
    </ion-toolbar>
</ion-footer>

@danielehrhardt
Copy link

I think this is not working with iPhone X or?

@ejerskov
Copy link

When I emulate on iPhone X theres space between the footer and the keyboard. As if the keyboardheight is to high? Any fix for that?

@abdoulsalamally
Copy link

@ejerskov
Keep getting the same error too any solution around? I've added the directive to app.module:

@NgModule({ declarations: [ MyApp, GroceryListMorePage, KeyboardAttachDirective ],

But still getting this error =>

Can't bind to 'keyboardAttach' since it isn't a known property of 'ion-footer'.

  1. If 'ion-footer' is an Angular component and it has 'keyboardAttach' input, then verify that it is part of this module.
  2. If 'ion-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
  3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
][keyboardAttach]="content"> ")

@prescindivel
Copy link

prescindivel commented May 30, 2019

Thanks @Manduro This worked perfectly with ionic 3, ios and android.

keyboard-android     keyboard-ios

@prescindivel
Copy link

prescindivel commented May 30, 2019

Hey @abdelsalamally try importing the Keyboard into the provider of your app.component, like this:

...
import { Keyboard } from '@ionic-native/keyboard';

...
...

@Component({
  selector: 'page-edit-document',
  templateUrl: 'edit-document.html',
  providers: [Keyboard]
})
...
...

@abdoulsalamally
Copy link

Hello @prescindivel I'm still getting the same error even after adding "Providers: [Keyboard] in app.component , I am afraid maybe I missed something by setting up the directive , would you mind elaborating step by step how you made this work ... Thanks in advance I've been struggling with this stuff for days now

@prescindivel
Copy link

@abdelsalamally what version of the ionic are you using?
Can you publish your code so I can see how you're doing?

@abdoulsalamally
Copy link

abdoulsalamally commented May 31, 2019

This is my ionic info :

`
Ionic:

Ionic CLI : 5.0.0 (C:\Users\Abd El Salam\AppData\Roaming\npm\node_modules\ionic)
Ionic Framework : ionic-angular 3.9.6
@ionic/app-scripts : 3.2.4

Cordova:

Cordova CLI : 9.0.0
Cordova Platforms : android 7.1.2
Cordova Plugins : cordova-plugin-ionic-keyboard 2.1.3, cordova-plugin-ionic-webview 2.2.1, (and 11 other plugins)

Utility:

cordova-res : not installed
native-run : not installed

System:

Android SDK Tools : 26.1.1 (C:\Users\Abd El Salam\AppData\Local\Android\Sdk)
NodeJS : v10.13.0 (C:\Program Files\nodejs\node.exe)
npm : 6.4.1
OS : Windows 10`

I first created a file called keyboard-attach.directive.ts in a folder called models then I imported it like this in my app.module.ts

import { KeyboardAttachDirective } from '../models/interfaces/keyboard-attach.directive';

then inside @ngModules like this:
`
@NgModule({
declarations: [
MyApp,
KeyboardAttachDirective

],`

Then in my html file where I want the keyboardattach to take effect like this:

<ion-footer [keyboardAttach]="content"> <ion-toolbar class="no-border" color="white"> <ion-input [(ngModel)]="newmessage" placeholder="Write your message ..."></ion-input> <ion-buttons end> <button ion-button (click)="addmessage()"> <ion-icon name="send" color="primary"></ion-icon> </button> </ion-buttons> </ion-toolbar> </ion-footer>

But in the .ts of the above html I didn't do anything so when I run ionic cordova build android --prod

I get this following nightmare :

`ionic-app-scripts.cmd build --prod --target cordova --platform android
[12:03:49] ionic-app-scripts 3.2.4
[12:03:50] build prod started ...
[12:03:50] clean started ...
[12:03:50] clean finished in 27 ms
[12:03:50] copy started ...
[12:03:50] deeplinks started ...
[12:03:51] deeplinks finished in 758 ms
[12:03:51] ngc started ...
[12:04:10] typescript error
Can't bind to 'keyboardAttach' since it isn't a known property of 'ion-footer'. 1. If 'ion-footer' is an
Angular component and it has 'keyboardAttach' input, then verify that it is part of this module. 2. If
'ion-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this
component to suppress this message. 3. To allow any property add 'NO_ERRORS_SCHEMA' to the
'@NgModule.schemas' of this component. (" <ion-footer [ERROR ->][keyboardAttach]="content">
<ion-inpu")

[12:04:10] ionic-app-script task: "build"
[12:04:10] Error: The Angular AoT build failed. See the issues above
Error: The Angular AoT build failed. See the issues above
at D:\Mystuffs\Projects\IONIC\chatApp\node_modules@ionic\app-scripts\dist\aot\aot-compiler.js:237:55
at step (D:\Mystuffs\Projects\IONIC\chatApp\node_modules@ionic\app-scripts\dist\aot\aot-compiler.js:32:23)
at Object.next (D:\Mystuffs\Projects\IONIC\chatApp\node_modules@ionic\app-scripts\dist\aot\aot-compiler.js:13:53)
at fulfilled (D:\Mystuffs\Projects\IONIC\chatApp\node_modules@ionic\app-scripts\dist\aot\aot-compiler.js:4:58)
[ERROR] An error occurred while running subprocess ionic-app-scripts.`

I even tried your solution of putting providers:[Keyboard] in app.component.ts but still the same issue , I also tried to include @ngModules.schemas like this to avoid the error:

` ],
schemas:[ CUSTOM_ELEMENTS_SCHEMA],
providers: [
StatusBar,
SplashScreen,
File,
FilePath,
FileChooser,
{provide: ErrorHandler, useClass: IonicErrorHandler},
AuthProvider,
AngularFireAuth,
UserProvider,
ImghandlerProvider,
UserProvider,
RequestsProvider,
ChatProvider,
GroupsProvider,
Camera,
CallNumber,
OneSignal,
Keyboard
]
})

But still no way!!!!!`

It's been days and days trying to find out how this ion-footer would go above the keyboard when someone tries to write something, actually the problemI have is that whenever I press in the "writing message" input , the keyboard covers the input and I can't see what I'm writing until I cancel the keyboard.. I thought perhaps this directive would tackle the issue but I can't manage to get ride of the above error.

Please @prescindivel any help would be appreciated .Thanks

@prescindivel
Copy link

@abdelsalamally
look my gist https://gist.github.com/prescindivel/cabc6912dd83f1e378c6dc5c734856ed

I'm use lazy load.

@abdoulsalamally
Copy link

Thanks a lot @prescindivel let me try out

@Youness-e
Copy link

Youness-e commented Oct 3, 2019

Updated version for ionic 4 and cordova-plugin-ionic-keyboard (https://github.com/driftyco/ionic-plugin-keyboard is deprecated)
https://gist.github.com/Youness-e/5c4f49f3aaa4ee90f45b75818764114d

Don't forget to install https://github.com/ionic-team/cordova-plugin-ionic-keyboard
ionic cordova plugin add cordova-plugin-ionic-keyboard
npm install @ionic-native/keyboard

and include the directive on your page.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { KeyboardAttachDirective } from 'src/app/directives/keyboard-attach.directive'; // Adapt the path

...

@NgModule({
imports: [
...
],
declarations: [XxxxxPage, KeyboardAttachDirective]
})
export class XxxxxPageModule {}

@Jonatthu
Copy link

Jonatthu commented Mar 5, 2020

What about ionic 5? This is not working and capacitor

@ipehimanshu
Copy link

any example for ionic 4 ?

@josedejesusAmaya
Copy link

any example for ionic 4 ?

Hello, were you able to figure out it for ionic 4? I have some troubles.
Thanks

@alfredcarro
Copy link

Hello, any working solution on capacitor (Ionic 5)?

@somq
Copy link

somq commented Aug 16, 2020

@alfredcarro @josedejesusAmaya @ipehimanshu @Jonatthu
Ionic 5 quickfix for components that return HtmlElement (ion-alert, ion-popover, etc...)

@alfredcarro
Copy link

My Fix on this was adding a hide and show when the user clicks on the input.
isPlatform('ios') && isShow <>content that overlaps</>
by this the overlap content hides whenever the user click the input and show when the user leaves the input by clicking the screen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment