-
-
Save Manduro/bc121fd39f21558df2a952b39e907754 to your computer and use it in GitHub Desktop.
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(); | |
} | |
} |
@Manduro? how can I use this directive? I want to know the step by step tutorial
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.
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
@Harshal111 Add keyboard provider in app.module.ts:
//...
import { Keyboard } from '@ionic-native/keyboard';
//...
providers: [
Keyboard,
//...
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.
it‘work,but the scollcontent is to large
+1 Worked for me.
I wrote keyboard attach directive for iOS 11.
https://gist.github.com/rdlabo/57bb9a2098f2f83c2c1cc16c8e88f6d5
please reference.
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.
Works great on iOS 11.2 👍 Thanks 😃
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')
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>
I think this is not working with iPhone X or?
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?
@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'.
- If 'ion-footer' is an Angular component and it has 'keyboardAttach' input, then verify that it is part of this module.
- If 'ion-footer' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
- To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
Thanks @Manduro This worked perfectly with ionic 3, ios and android.
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]
})
...
...
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
@abdelsalamally what version of the ionic are you using?
Can you publish your code so I can see how you're doing?
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
@abdelsalamally
look my gist https://gist.github.com/prescindivel/cabc6912dd83f1e378c6dc5c734856ed
I'm use lazy load.
Thanks a lot @prescindivel let me try out
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 {}
What about ionic 5? This is not working and capacitor
any example for ionic 4 ?
any example for ionic 4 ?
Hello, were you able to figure out it for ionic 4? I have some troubles.
Thanks
Hello, any working solution on capacitor (Ionic 5)?
@alfredcarro @josedejesusAmaya @ipehimanshu @Jonatthu
Ionic 5 quickfix for components that return HtmlElement (ion-alert, ion-popover, etc...)
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.
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?