Skip to content

Instantly share code, notes, and snippets.

@Manduro
Last active August 24, 2020 06:50
Show Gist options
  • 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();
}
}
@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