Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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();
}
}
@kitkimwong

This comment has been minimized.

Copy link

@kitkimwong kitkimwong commented Oct 4, 2016

well done guy!

@imtiaz-ahmed233

This comment has been minimized.

Copy link

@imtiaz-ahmed233 imtiaz-ahmed233 commented Oct 15, 2016

We are exploring ionic 2. Can you please let us know how to use this directive and where?

@ddiesenreither

This comment has been minimized.

Copy link

@ddiesenreither ddiesenreither commented Oct 18, 2016

Hi man,

really nice directive. But can we somehow achieve a smoother movement of the footer. E.g. a transition or something?

Many thanks, Diesi

@arturalkaim

This comment has been minimized.

Copy link

@arturalkaim arturalkaim commented Oct 20, 2016

Hi! Thanks for this!
It is working great on Android but nothing happened with iOS and the input remains hidden.
I'm testing on an iPhone with iOS 10

Any help?

@jlsuarezs

This comment has been minimized.

Copy link

@jlsuarezs jlsuarezs commented Nov 1, 2016

For a better transition you should use the WkWebView Plugin...@diesenreither

@Manduro

This comment has been minimized.

Copy link
Owner Author

@Manduro Manduro commented Nov 10, 2016

@pinrostudio You can find an example in the comment block.

@ddiesenreither You could certainly add an animation, but it's impossible to recreate the animation of the native iOS keyboard. So it will never be nicely pushed up by the keyboard.

@arturalkaim This directive does not do anything on Android, only on iOS. It should work if you follow the example.

@schubertq

This comment has been minimized.

Copy link

@schubertq schubertq commented Dec 1, 2016

good job!
I met a issue on the iOS platform,when the footer is at the bottom,the button can receive click event;but when the keyboard shows, if you click the button, it just hide the keyboard, the button can not receive click event? Could you help me to handle this problem? Thanks very much! Below is my code.
<ion-footer [keyboardAttach]="content"> <ion-toolbar> <ion-item> <ion-input placeholder="edit" type="text"></ion-input> <button ion-button clear item-right (click)="send()"> send </button> </ion-item> </ion-toolbar> </ion-footer>

@pdrosos

This comment has been minimized.

Copy link

@pdrosos pdrosos commented Jan 5, 2017

@Manduro Thanks for the directive!
I have the same issue with Send button. Any help will be appreciated. Thanks!

@matejamateusz

This comment has been minimized.

Copy link

@matejamateusz matejamateusz commented Jan 11, 2017

@schubertq have you resolve your issue? unfortunately have the same ;/

@pdrosos

This comment has been minimized.

Copy link

@pdrosos pdrosos commented Jan 12, 2017

@schubertq @matejamateusz
I opened an issue: ionic-team/ionic-framework#9978 You can also write there and describe your issues.

@cryptocoinserver

This comment has been minimized.

Copy link

@cryptocoinserver cryptocoinserver commented Jan 24, 2017

typeerror

"rxjs": "5.0.3"

@cryptocoinserver

This comment has been minimized.

Copy link

@cryptocoinserver cryptocoinserver commented Jan 24, 2017

My Fork solves this error. I couldn't test it on a device yet.

@REPTILEHAUS

This comment has been minimized.

Copy link

@REPTILEHAUS REPTILEHAUS commented Feb 10, 2017

Great snippet.. but having the same issue with the send button.. keyboard pushed the footer up perfectly but clicking the send button makes the keyboard retreat and the send button drop down also, it is then necessary to click it a second time when it is back in its resting state.. anyone have any fixes for this yet ?

@derasmus

This comment has been minimized.

Copy link

@derasmus derasmus commented Mar 6, 2017

Same issue with the send button, any update?

@antoine92190

This comment has been minimized.

Copy link

@antoine92190 antoine92190 commented Mar 13, 2017

To fix the issue with the send button, you can add the following code in your css file:

.input-cover {
position: static;
}

@Manduro

This comment has been minimized.

Copy link
Owner Author

@Manduro Manduro commented Mar 21, 2017

@mysecondworld I ran into this as well some time ago and I believe the problem is tied to a specific version of rxjs.

@schubertq @pdrosos @matejamateusz @REPTILEHAUS @derasmus @antoine92190
When a button is clicked, the input loses focus, which logically causes the keyboard to hide. You can use some basic JavaScript to make sure that the input does not lose focus when clicking the button. I'm using something like this:

 <ion-footer [keyboardAttach]="content">
   <ion-toolbar>
     <input type="text" #input>
     <button ion-button (tap)="send(input, $event)">Send</button>
   </ion-toolbar>
 </ion-footer>
send(input: HTMLInputElement, event: MouseEvent) {
  // Prevent default behaviour of this click event
  event.preventDefault();

  // Insert logic for actually sending data here

  // Reset input to empty and set focus
  input.value = '';
  input.focus();
}
@alain-sarti

This comment has been minimized.

Copy link

@alain-sarti alain-sarti commented Mar 22, 2017

I am still struggling with the ios keyboard problem. The usage as described above didn't work for me, I have to use it with
keyboardAttach="content" rather than [keyboardAttach]="content" (otherwise I get the error: Unhandled Promise rejection: Template parse errors: Can't bind to 'keyboardAttach' since it isn't a known property of 'ion-footer'..
But if I do use it that way, the keyboard behaviour doesn't change. Is there a way to overcome this error? I'm using ionic 2.2.0

@Manduro

This comment has been minimized.

Copy link
Owner Author

@Manduro Manduro commented Apr 1, 2017

@alain-sarti Make sure to include the directive in your app.module.ts and use the [] around it in your HTML. Try the guide in the Angular docs if you need more info!

@murugan5895

This comment has been minimized.

Copy link

@murugan5895 murugan5895 commented Apr 5, 2017

Unhandled Promise rejection: 
"Template parse errors:
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.
 (\"
<ion-footer [ERROR ->][keyboardAttach]=\"content\">
  <ion-toolbar>
    <ion-buttons *ngIf=\"curpg !='mainpg'\" class=\"item-ico\"): TicketaddPage@422:12"
"; Zone:"
"<root>"
"; Task:"
"Promise.then"
"; Value:"

@Manduro Please help me to solve this issue.I integrate everything as mentioned above in app.module.ts also initialise the directory.I don't know why this error is coming ?

@murugan5895

This comment has been minimized.

Copy link

@murugan5895 murugan5895 commented Apr 14, 2017

@Manduro I found the solution i missed in the app.modules after import i didnt mention the @ngModules ({declaration:[KeyboardAttachDirective]}) for this only it show this errors if anyone have related to this problem please follow this .The directory is working fine thanks man.

@jerrydeng

This comment has been minimized.

Copy link

@jerrydeng jerrydeng commented Apr 20, 2017

@antoine92190 I have the click event on tag and the click event still won't fire with input-cover css. @Manduro, I'm not trying to keep the focus in the input box. But instead trying to click on a button and the button will trigger another function. However, since there's another listener behind the footer, it consistently trigger that event instead of whatever is on the keyboardAttached button. I've tried event.stopPropagation() and it stills brings that up and doesn't handle the click event on the button in the footer.

@jerrydeng

This comment has been minimized.

Copy link

@jerrydeng jerrydeng commented Apr 20, 2017

It turns out that the event on footer never gets fired because setElementPosition happened too early. Not sure what's a good approach this. setTimeout does the trick but not reliably and cause some strange lag on when to resize/reposition the footer content. If I switched it to a faster listener like tap, it will work almost all the time having it fire quick enough.

@ivanov84

This comment has been minimized.

Copy link

@ivanov84 ivanov84 commented Apr 27, 2017

"tap event" works for ionic 3.0.1! confirmed! Thanks a lot!

@anphu7492

This comment has been minimized.

Copy link

@anphu7492 anphu7492 commented May 3, 2017

@jerrydeng tap event works fine, thanks for the tip 👍

@maitham

This comment has been minimized.

Copy link

@maitham 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

This comment has been minimized.

Copy link

@jsmithangular jsmithangular commented Jul 9, 2017

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

@YasirSherzad

This comment has been minimized.

Copy link

@YasirSherzad YasirSherzad commented Jul 20, 2017

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.

@harshal111

This comment has been minimized.

Copy link

@harshal111 harshal111 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

This comment has been minimized.

Copy link

@peterprice peterprice commented Jul 23, 2017

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

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

This comment has been minimized.

Copy link

@rdlabo 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

This comment has been minimized.

Copy link

@CK110 CK110 commented Oct 20, 2017

it‘work,but the scollcontent is to large

@pingu1m

This comment has been minimized.

Copy link

@pingu1m pingu1m commented Oct 31, 2017

+1 Worked for me.

@rdlabo

This comment has been minimized.

Copy link

@rdlabo rdlabo commented Dec 12, 2017

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

please reference.

@JacoRoos

This comment has been minimized.

Copy link

@JacoRoos JacoRoos commented Feb 21, 2018

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

This comment has been minimized.

Copy link

@piraveen piraveen commented Mar 9, 2018

Works great on iOS 11.2 👍 Thanks 😃

@WolffDev

This comment has been minimized.

Copy link

@WolffDev 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

This comment has been minimized.

Copy link

@ejerskov 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

This comment has been minimized.

Copy link

@danielehrhardt danielehrhardt commented Jun 11, 2018

I think this is not working with iPhone X or?

@ejerskov

This comment has been minimized.

Copy link

@ejerskov ejerskov commented Sep 15, 2018

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

This comment has been minimized.

Copy link

@abdoulsalamally abdoulsalamally commented May 29, 2019

@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

This comment has been minimized.

Copy link

@prescindivel prescindivel commented May 30, 2019

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

keyboard-android     keyboard-ios

@prescindivel

This comment has been minimized.

Copy link

@prescindivel 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

This comment has been minimized.

Copy link

@abdoulsalamally abdoulsalamally commented May 31, 2019

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

This comment has been minimized.

Copy link

@prescindivel prescindivel commented May 31, 2019

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

@abdoulsalamally

This comment has been minimized.

Copy link

@abdoulsalamally 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

This comment has been minimized.

Copy link

@prescindivel prescindivel commented May 31, 2019

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

I'm use lazy load.

@abdoulsalamally

This comment has been minimized.

Copy link

@abdoulsalamally abdoulsalamally commented May 31, 2019

Thanks a lot @prescindivel let me try out

@Youness-e

This comment has been minimized.

Copy link

@Youness-e 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

This comment has been minimized.

Copy link

@Jonatthu Jonatthu commented Mar 5, 2020

What about ionic 5? This is not working and capacitor

@ipehimanshu

This comment has been minimized.

Copy link

@ipehimanshu ipehimanshu commented Mar 16, 2020

any example for ionic 4 ?

@josedejesusAmaya

This comment has been minimized.

Copy link

@josedejesusAmaya josedejesusAmaya commented Apr 6, 2020

any example for ionic 4 ?

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

@alfredcarro

This comment has been minimized.

Copy link

@alfredcarro alfredcarro commented Aug 5, 2020

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

@somq

This comment has been minimized.

Copy link

@somq somq commented Aug 16, 2020

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

@alfredcarro

This comment has been minimized.

Copy link

@alfredcarro alfredcarro commented Aug 24, 2020

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