Ionic Framework Keyboard hides input field - angularjs

I am having some issues in a form I am creating. This form:
<form name="myForm">
<label ng-hide="hide" class="item item-input" >
<span class="input-label">How much minutes?</span>
<input ng-pattern="onlyNumbers" name="number" type="text" ng-model="taskMinutes">
</label>
</form>
Is almost in the middle of the screen but when the user taps on the input field to start typing, the focus is not being correctly executed. The keyboard shows but it is hiding the field. If I start typing, the focus gets executed and the screen moves accordingly. Any tips on how I can fix this?
Update: This is the whole screen:
<ion-view>
<ion-content>
<div class="list">
<label class="item item-input">
<span class="input-label">Task</span>
<input type="text" ng-model="taskInfo">
</label>
<label class="item "> Can this task be measured?
<p>
<ion-checkbox ng-repeat="item in devList"
ng-model="item.checked"
ng-checked="item.checked"
ng-click="change(item)">
{{ item.text }}
</ion-checkbox>
</p>
</label>
<form name="myForm">
<label ng-hide="hide" class="item item-input" >
<span class="input-label">How much minutes?</span>
<input ng-pattern="onlyNumbers" name="number" type="tel" ng-model="taskMinutes">
</label>
</form>
<label class="item" ng-controller="tasksCtrl">
<button ng-disabled="!myForm.number.$valid" class="button button-block button-royal" type="submit" ng-click="addTask()">Add Task</button>
</label>
</div>

This is how I solved it:
NOTE: you have to install cordova keyboard plugin (https://github.com/driftyco/ionic-plugin-keyboard)
var windowHeight = window.innerHeight;
$scope.$on('$ionicView.loaded', function() {
// fallback + warning
var scrollView = {scrollTo: function() { console.log('Could not resolve scroll delegate handle'); }};
var setupKeyboardEvents = function() {
$scope.unbindShowKeyboardHandler = $scope.$on('KeyboardWillShowNotification',
function(info) {
var input = angular.element(document.activeElement);
var body = angular.element(document.body);
var top = input.prop('offsetTop') //+ angular.element(input.prop('offsetParent')).prop('offsetTop');
var temp = angular.element(input.prop('offsetParent'));
var tempY = 0;
while (temp && typeof(temp.prop('offsetTop')) !== 'undefined') {
tempY = temp.prop('offsetTop');
top += tempY;
temp = angular.element(temp.prop('offsetParent'));
}
top = top - scrollView.getScrollPosition().top;
var inputHeight = input.prop('offsetHeight');
var keyboardHeight = info.keyboardHeight;
var requiredSroll = windowHeight - keyboardHeight > top + inputHeight + 11 ? 0 : windowHeight - keyboardHeight - top - inputHeight - 12;
$timeout(function(){ scrollView.scrollTo(0, - requiredSroll || 0, true); });
});
$scope.unbindHideKeyboardHandler = $scope.$on('KeyboardWillHideNotification', function() {
$timeout(function(){ scrollView.scrollTo(0, 0, true); });
});
};
$timeout(function(){
var instances = $ionicScrollDelegate.$getByHandle('your-scroll-handle')._instances;
instances.length && (scrollView = instances[instances.length - 1]);
}).then(setupKeyboardEvents);
});
$scope.$on('$destroy', function(){
$scope.unbindShowKeyboardHandler();
$scope.unbindHideKeyboardHandler();
});
and on application run:
window.addEventListener('native.keyboardshow', keyboardShowHandler);
window.addEventListener('native.keyboardhide', keyboardHideHandler);
function keyboardShowHandler(info){
//alert('Keyboard height is: ' + e.keyboardHeight);
console.log("KeyboardWillShowNotification: " + JSON.stringify(info));
$rootScope.$broadcast('KeyboardWillShowNotification', info);
}
function keyboardHideHandler(info){
$rootScope.$broadcast('KeyboardWillHideNotification', info);
}
and in the template:
<ion-content scroll-handle="your-scroll-handle">

I was having this exact issue yesterday!
Each of the elements on the page had lots of different padding declarations that were conflicting and this broke my form.
Please try removing all styling from the page to see if this fixes it. If it does, add back the styling element-by-element to pinpoint which one is breaking your form.
Hope this helps!

Solved for ionic V1. Just add the fixed as below.
Add "delegate-handle" in the template file.
<ion-content class="padding" overflow-scroll="false" delegate-handle="myInput">
then add function on input field for animate when keyboard open.
<input type="text" id="user" ng-model="user" ng-focus="scrollUP(); keyboardFocus('dnsInput');">
Add the injectable dependency inside the controller
angular.module('starter.user', []).controller('userCtrl', function($scope, $state, $http, $ionicScrollDelegate) {
....
$scope.scrollUP = function () {
if ( app.isAndroid() ) {
document.querySelector("#user").scrollIntoView(false);
}
}
$scope.keyboardFocus=function(handleValue){
if ( app.isAndroid() ) { //check for android platform
$timeout(function(){
$ionicScrollDelegate.$getByHandle(handleValue).scrollBottom();
}, 500);
}
}
});
Make sure to include the ionic keyboard latest version. currently, I used "com.ionic.keyboard": "2.2.1",
For native scrolling, Add the code in app.js
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$ionicConfigProvider.platform.android.scrolling.jsScrolling(true);
.....
}
Enjoy..

The way that I found was to add the class hide-on-keyboard-open of ionic in all components that doesn't uses the keyboard. So this way I do not need to scroll the page cause with this components hidden I can see all I need to do with the keyboard open.

Without Using Any Plugin
This worked for me and currently using in more than 10 apps
NOTE : Please specify reason in comment For Vote Down
Just Add style="height: 400px;" in ion-content Its height Of
keyboard
<ion-view view-title="My Page">
<ion-content>
Hello!
<div style="height: 400px;"></div>
</ion-content>
</ion-view>
Logic explanation : In Phone or Tablet
<ion-view> Is not Scrollable
But
<ion-content> Is Scrollable
So when you scroll its <ion-content> that scrolls and <ion-view> is DEAD , STIFF Never scrolls

Related

Angularjs multiple functions

I have 2 buttons:
One scans a QR code and returns the values which works.
Another on the same page that confirms the input values, but I cannot get the second function to fire.
I have 2 inputs, deviceid and companyid, and 2 buttons. The scan button, via ng-click, calls scanQR and the second button, also via ng-click, calls checkBlanks.
A confirm ID button calls a functions to firstly check for blanks then alert the user if the input data is missing. Once the 2 inputs have content it will save the data via the verifyDetails() call. But I cannot get the checkBlanks function to run.
HTML Code is:-
<ion-view title="Settings">
<ion-content padding="true" class="has-header">
<form class="list">
<label class="item item-input" name="deviceid">
<span class="input-label">Device ID</span>
<input type="text" placeholder="" ng-model="deviceid">
</label>
<label class="item item-input" name="companyid">
<span class="input-label">Company ID</span>
<input type="text" placeholder="" ng-model="companyid">
</label>
</form>
<button ng-click="scanQR()" class="button button-positive button-block">Scan QR to Configure</button>
<button ng-click="checkBlanks()" class="button button-positive button-block">Confirm ID</button>
<form class="list">
<ion-toggle toggle-class="toggle-positive" ng-checked="true">Vibrate</ion-toggle>
<ion-toggle toggle-class="toggle-positive">Light on Scan</ion-toggle>
<div style="text-align:center;" class="show-list-numbers-and-dots">
<p style="color:#000000;font-size:10px;">On Android devices set to off and use the volume controls to turn the flashlight on or off.</p>
</div>
<ion-radio ng-model="radioCheck" value="security">Security</ion-radio>
<ion-radio value="utilities">Utilities</ion-radio>
</form>
</ion-content>
</ion-view>
AngularJS is:-
function($scope, $stateParams) {
$scope.radioCheck = "security";
$scope.scanQR = function() {
cordova.plugins.barcodeScanner.scan(
function(result) {
var TagResponse = result.text;
var config = TagResponse.indexOf("Config:");
if (TagResponse !== '') {
if (config === 0) {
var ConfigVals = TagResponse.split(':');
$scope.deviceid = ConfigVals[1];
$scope.companyid = ConfigVals[2];
$scope.$apply();
}
}
});
};
$scope.checkBlanks = function() {
alert("Device ID" + $scope.deviceid);
console.log("Device ID" + $scope.device)
if ($scope.deviceid === '') {
alert("Please enter a device ID", Dismissed, "Error");
} else if ($scope.companyid === '') {
alert("Please enter a Company ID", Dismissed, "Error");
} else {
verifyDetails();
}
};
}
Any help appreciated, I'm very new to Angularjs and Ionic.

Using Angular ng-show/ng-hide with radio buttons

I'm using $scope.checked to show/hide the "Top" text box, name="numRows" in my html.
However, even when I click on the 'top' radio button, $scope.checked always retains the value of `all' when I debug my controller code.
This simply plunker seems to work fine, http://plnkr.co/edit/6GoUZw7zkf8oqUmKg9hf?p=preview, but it won't work in my application.
In the plunker, there's a simple button whose click value will hit the controller event $scope.showval to show the value of either "top" or "all".
My HTML:
<div class="form-group">
<div class="row-fluid">
<label class="col-md-2 col-lg-2 control-label" for="numRows">Returned Rows</label>
<!-- ALL ROWS RADIO -->
<div class="col-md-1 col-lg-1">
<label class="radio-inline" for="radio-all">
<input name="radios" id="radio-all" value="all" type="radio" ng-model="checked" ng-click="setTopRows('all')">All
</label>
</div>
<!-- TOP NUM OF ROWS RADIO -->
<div class="col-md-1 col-lg-1">
<label class="radio-inline" for="radio-top">
<input name="radios" id="radio-top" value="top" type="radio" ng-model="checked" ng-click="setTopRows('top')">Top
</label>
</div>
<!-- NUM OF ROWS TEXT BOX -->
<div class="col-md-2">
<input ng-show="checked == 'top'" ng-hide="checked == 'all'" type="text" class="form-control" name="numRows" ng-model="settings.numRowsReturned" placeholder="" >
</div>
<div class="col-md-3">
Click to show<input type="button" ng-click="showval(e)">
</div>
</div>
</div>
A snippet from my angular controller code :
The $scope.checked value is always 'all', even when I click on 'top' from the html.
(function () {
'use strict';
angular.module('rage')
.controller('GadgetSettingsCtrl_NEW', ['$rootScope', '$scope', '$modalInstance', gridSettings]);
function gridSettings($rootScope, $scope, $modalInstance,) {
var settings = this;
$scope.checked = 'all';
$scope.showval = function (e) {
var test = $scope.checked;
}
$scope.setTopRows = function (numRows) {
if (numRows === 'top') {
$scope.checked = 'top';
}
else {
$scope.checked = 'all';
}
}
function checkOptions(){
var top = '';
if ($scope.checked === 'top') {
top = (settings.numRowsReturned != undefined ? settings.numRowsReturned : '');
}
}
}; // end of gridSettings()
})();
Can someone help me clear up why $scope.checked is NOT changing when I click on the radio buttons ?
thank you,
Bob
****** UPDATE *********
I've added a simple ng-click="setTopRows('all')" to force my scope variable to change. This works, but it seems like too much code to accomplish this.

ionic modal scope not working using $ionicModal.fromTemplateUrl()

I am trying to open an ionic modal just after logging in to an app. The modal is opening fine along with the data. The problem is when i attaching ng-click event corrosponding to OK or CANCEL button, it is not working.The function is not called.Maybe there is a problem with the scope. I cant figure out why..
This is the controller
$scope.dummyData = NetworkDisplay.getHospitals();
console.log($scope.dummyData.inviteToNetwork);
if ($scope.dummyData.inviteToNetwork) {
$ionicModal.fromTemplateUrl('templates/network/modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
$scope.modal.show();
console.log($scope.dummyData);
$scope.ok = function(data) {
for (var i = 0; i < data.length; i++) {
if (data[i].checked === true)
HospitalsNetwork.set(data[i]);
// console.log(data[i].checked);
}
$scope.modal.remove();
$state.go('tab.networks');
};
$scope.cancel = function() {
$scope.modal.remove();
$state.go('tab.dashboard');
};
This is my modal.html
<ion-view>
<ion-content>
<div class="card">
<p class="padding">Do you like the following hospitals to be added to your network?</p>
<!--<ul class="list">
<li class="item item-checkbox" ng-repeat="hospital in dummyData.inviteToNetwork">
<label class="checkbox">
<input type="checkbox">
</label>
Flux Capacitor
</li>
</ul>-->
<div class="list">
<ion-checkbox ng-repeat="hospital in dummyData.inviteToNetwork" ng-model="hospital.checked">
{{hospital.name}}
</ion-checkbox>
</div>
<!-- <div class="modal-footer"> -->
<button type="button" ng-click="ok(dummyData.inviteToNetwork)">OK</button>
<button type="button" ng-click="cancel()">Cancel</button>
<!-- </div> -->
</div>
</ion-content>
</ion-view>
I was stuck in the same and finally figured out that it is not working on Ionic app but it is working on IOS emulator.
So finally you can't able to test Ionic modal on Ionic app till the Ionic team will fix this issue.

Angular Material - Dynamically add tab and change to that tab

Currently working on a chat app here https://playwithfire.firebaseapp.com/ and whenever a user adds a new room I want the new room tab to be entered. Currently you can add a room but need to click it afterwards to enter that room and display its content.
I tried changing the attribute md-selected="selectedIndex" but that makes no tab active so no content appears.
Is it possible to do what I'm asking for? What I've got so far:
index.html
<div layout="column" ng-controller="RoomController">
<!-- Tabs Container -->
<md-tabs md-stretch-tabs md-selected="selectedIndex">
<!-- Individual Tab -->
<md-tab ng-repeat="room in roomList"
label="{{room.roomName}}">
<div ng-controller="ChatController">
<!-- Display messages -->
<md-list>
<md-item ng-repeat="msg in messages">
<md-item-content>
<div class="md-tile-content">
<div class="bubble">
<strong>{{msg.from}}</strong><br>
{{msg.body}}
</div>
</div>
</md-item-content>
</md-item>
</md-list><!--/DisplayMessages-->
<!-- Chat controls -->
<div layout="row" layout-margin layout-wrap>
<div flex="33">
<!-- Assign username -->
<label for="nameInput">Username</label>
<input ng-model="name" type="text" id="nameInput" placeholder="Enter a username...">
</div>
<div flex="95">
<!-- Post a message -->
<label>Message</label>
<textarea class="form-control"
ng-model="msg"
ng-keydown="addMessage($event)"
id="messageInput"
placeholder="Type a message...">
</textarea>
</div>
<div layout="row" layout-sm="column" layout-margin layout-fill layout-align="start end">
<!-- Click to send message -->
<div flex>
<md-button class="md-raised md-primary pull-left" ng-click="sendMessage()">Send</md-button>
</div>
<!-- Modal to add or join room -->
<div flex ng-controller="ModalController">
<md-button class="md-raised md-primary pull-left" ng-click="open()">Add or Join Room</md-button>
</div>
<!-- Opens helper -->
<div flex ng-controller="HelpController">
<md-button class="pull-right" ng-click="open()" ng-href="">Need help?</md-button>
</div>
</div>
</div><!--/ChatController-->
</md-tab>
</md-tabs><!--/tabs container-->
</div><!--/RoomController-->
room.js
angular.module('myApp')
.controller('RoomController', function($scope, ShareFactory) {
$scope.roomList = ShareFactory.roomList;
// use this to default to index 0 in roomList
$scope.selectedIndex = 0;
$scope.$on('RoomChange', function(event, data) {
$scope.selectedIndex = data;
console.log('Heard the change!');
console.log('The data is: ' + data);
});
});
modal.js
angular.module('myApp')
.controller('ModalController', function($rootScope, $scope, $modal, ChatFactory, ShareFactory) {
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'views/modal.html',
controller: 'ModalInstanceController'
});
modalInstance.result.then(function (name) {
var found = false;
var length = ShareFactory.roomList.length;
var index = 0;
for(var i = 0; i < length; ++i) {
if(ShareFactory.roomList[i].roomName === name) {
found = true;
index = i;
console.log('index ' + index);
}
}
if(!found) {
ShareFactory.roomList.push({ roomName : name});
index = ShareFactory.roomList.length - 1;
}
else {
// don't care about disabled, not a feature i want to use
//ShareFactory.roomList[index].disabled = false;
}
// Broadcast event to all children of rootScope
// namely want RoomController to listen for this change
$rootScope.$broadcast('RoomChange', index);
}, function () {
console.log('cancel');
});
};
});
Ya know, this definitely came up in a Github issue a while ago, but it may have been kicked to the backlog due to other high priority issues.
I just added this feature to master:
https://github.com/angular/material/commit/8285e2d0bb6efbc72e311ee85b619cbbe8437072
And it should be viewable shortly on our site in the second demo:
https://material.angularjs.org/HEAD/#/demo/material.components.tabs
In the meantime, you should be able to solve this by adding the following code:
if(!found) {
ShareFactory.roomList.push({ roomName : name});
index = ShareFactory.roomList.length - 1;
$timeout(function () {
ShareFactory.selectedIndex = index;
});
}
The $timeout is necessary because you must wait until after the render is finished before you can update the selected index to the new one - otherwise, it will think that the valid is out of range.
Hope this helps!

AngularJS : Hide and show radio button

<div class="filter_hide">
<div ng-cloak ng-repeat="web in website" >
<label ng-show="filter[web.websiteId]"><input type="radio" id="{{web.websiteId}}" ng-checked="webCheck" id="{{web.websiteId}}" value="{{web.websiteId}}" name="webname" ng-model="filter[web.websiteId]" />{{web.websiteName}} ({{web.couponCount}})</label>
</div>
</div>
<div class="filter_show">
<div class="check_box" ng-hide="filter[web.websiteId]" ng-repeat="web in website">
<label><input type="radio" value="{{web.websiteId}}" ng-checked="webCheck" id="{{web.websiteId}}" name="webname" ng-click="webcall(web)" ng-model="filter[web.websiteId]" />{{web.websiteName}} ({{web.couponCount}})</label>
</div>
</div>
I am trying to make when some one click on radio button form "filter_show" div then need to hide form there and show on "filter_hide" div and if user again click another radio button form "filter_show" div then need to hide previously select radio button form "filter_hide" div and show new one there.
I am using angular js 1.2.17
my controller -
app.controller('myCtrl', function ($scope, $http) {
$http({method: 'GET', url: '/asasa/asa/'}).success(function(data) {
$scope.website = data.websites;
$scope.onlinedata = data.coupons;
$scope.restdata = $scope.onlinedata;
$scope.webcall = function (web) {
$http({method: 'GET',url: '/asas/cccc/asas?websiteId='+web.websiteId}).success(function(data) {
$scope.onlinedata = data.coupons;
});
};
Take a look a this example
fiddle Example
<div ng-app>
<div ng-controller='contorller'>
<div class='to_hide' ng-if='hide === true'>
<input type="radio" name='hide' ng-click="showElement('show')" />Hide<br>
<input type="radio" name='hide' ng-click="showElement('show')" />Hide<br>
</div>
<br>
<div clas='to_show' ng-if='hide === false'>
<input type="radio" name='show' ng-click="showElement('hide')" />Show</br>
<input type="radio" name='show' ng-click="showElement('hide')" />Show</br>
</div>
</div>
</div>
<script>
function contorller($scope){
$scope.hide = true;
$scope.showElement = function(value){
if(value === 'hide'){
$scope.hide = true;
}else{
$scope.hide = false;
}
}
}
</script>

Resources