I am new to ionic therefore to cordova so in my controllers .js i am having a function defined as :
$scope.deleteFingerPrint = function() {
$scope.disableFingerPrint = true;
ss.remove(
function(key) {
console.log('Removed ' + key);
},
function(error) {
console.log('Error, ' + error);
},
'token');
localStorage.removeItem('isFingerPrintRequired');
localStorage.removeItem('hasEnrolledFingerprints');
isFromIosUserValidation = false;
$scope.deletePopup.close();
$ionicSideMenuDelegate.toggleLeft();
}
The code works fine but if i try to modify it like this:
$scope.deleteFingerPrint = function() {
$scope.disableFingerPrint = true;
ss.remove(
function(key) {
console.log('Removed ' + key);
},
function(error) {
console.log('Error, ' + error);
},
'token');
localStorage.removeItem('isFingerPrintRequired');
localStorage.removeItem('hasEnrolledFingerprints');
if (isIOS == true) {
isFromIosUserValidation = false;
}
$scope.deletePopup.close();
$ionicSideMenuDelegate.toggleLeft();
}
The popup comes but $scope.deletePopup.close(); doesnot works and the popup remains as it is.
What is the issue and why it is not getting closed. I have mentioned isIOS and isFromIosUserValidation globally.
Where did you define your isIOS variable, maybe the condition is not working so it give error. Please write code properly to understand the problem.
Related
I have some page which contain register with facebook button which I set hidden with ng-hide="fbLoggedIn" and form input which I set hidden with ng-show="fbLoggedIn"
My goal is register with facebook button will hide if fbLoggedIn set to true and form input will show if fbLoggedIn set to true.
register facebook button ng-click="registerFb()" execute this function
$scope.registerFB = function () {
authService.fbLogin();
$scope.fbLoggedIn = authService.fb_logged_in();
console.log($scope.fbLoggedIn); //this show false even `fb_access_token` not null
}
Here is my authService.fbLogin and authService.fb_logged_in function
authService.fbLogin = function () {
var FB = window.FB;
FB.login(function(response) {
console.log(response);
if (response.authResponse) {
sessionService.set('fb_id', response.authResponse.userID);
sessionService.set('fb_access_token', response.authResponse.accessToken);
sessionService.set('fb_expiration_date', new Date(new Date().getTime() + response.authResponse.expiresIn * 1000).toISOString());
//console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
console.log(response);
});
} else {
console.log('User cancelled login or did not fully authorize.');
//console.log(response);
}
});
};
authService.fb_logged_in = function () {
if(sessionService.get('fb_access_token') != null){
return true;
}else {
return false;
}
};
In other function I try to check if fb_access_token is not null, just to make sure something wrong with my logic, and the result is true.
With above debuggin I can say that $scope.fbLoggedIn = authService.fb_logged_in(); execute before authService.fbLogin(); finish.
So how I can execute $scope.fbLoggedIn = authService.fb_logged_in(); after authService.fbLogin(); finish? maybe how to achieve my goal?
Alright. This can be achieved using promise. I don't know the parameters you have included in your autService service, so I will be making a factory of the same name with the new parameters that you might need to add.
Hence, according to me, this is how your factory should be.
angular.module('YourModuleName').factory('authService',['$http','$q',function($http,$q){
var obj = {};
obj.fbLogin = function () {
var defer = $q.defer();
var FB = window.FB;
FB.login(function(response) {
console.log(response);
if (response.authResponse) {
sessionService.set('fb_id', response.authResponse.userID);
sessionService.set('fb_access_token', response.authResponse.accessToken);
sessionService.set('fb_expiration_date', new Date(new Date().getTime() + response.authResponse.expiresIn * 1000).toISOString());
FB.api('/me', function(response) {
console.log(response);
defer.resolve('Good to see you, ' + response.name + '.');
});
}
else {
defer.reject('User cancelled login or did not fully authorize.');
}
});
return defer.promise;
}
obj.fb_logged_in = function () {
if(sessionService.get('fb_access_token') != null){
return true;
}else {
return false;
}
};
return obj;
}])
And thus, the function call from the controller should be as follows.
$scope.registerFB = function () {
authService.fbLogin().then(function(response){
$scope.fbLoggedIn = authService.fb_logged_in();
console.log($scope.fbLoggedIn);
},function(error){
console.error("Error : ",error);
});
}
Note: CODE NOT TESTED.
Hence it would solve the problem with the best practices of angularJS
use the $rootscope to assign values they provide event emission/broadcast and subscription facility.
I was trying to implement login form by authenticating the credentials from data stored in json file. But i'm getting error like only first case is working.It's just a demo application trying to learn the concepts:
this is my controller:
var app = angular.module('myApp', []);
app.controller("myCtrl",function($scope, $http)
{
$scope.check = function(){
var sample;
$http.get('roles.json').then(function(res)
{
sample = res.data;
console.log(sample);
angular.forEach(sample, function(val)
{
if($scope.uName===val.userName)
{
if($scope.password===val.password)
{
alert("sucess");
}
else
{
alert("failure");
}
}
else
{
alert("failure");
}
});
}); // end of http
};// end of function
});
data is loading properly but seems like some problem in logic.
data in json:
[
{"userName":"stud101","password":"stud1","role":"student"},
{"userName":"stud102","password":"stud2","role":"student"},
{"userName":"superlib","password":"lib1","role":"Librarian"}
]
I'm getting success only with first case, in rest other cases failure.
$http.get('roles.json').then(function(res){
sample = res.data;
console.log(sample);
var isMatched = false;
angular.forEach(sample, function(val)
{
if($scope.uName==val.userName && $scope.password==val.password)
{
isMatched = true;
return false; // To stop the foreach loop if username and password both are matched.
}
});
if(isMatched)
{
alert("success");
}
else
{
alert("failure");
}
});
angular.forEach($scope.messagepool, function(value, key) {
if(value.userName==$scope.uName && value.password==$scope.password){
alert('success');
}else{
alert('faluire');
}
});
Use this instead of your foreach . Hope this helps (y)
I have multiple INSERTs I'd like to be done before starting SELECT requests. My problem is that the INSERT is not yet finished when the SELECT fires.
Made a factory for the database handling:
databaseFactory.js
factory.insertIntoTable= function (database, data) {
var sqlCommand = 'INSERT INTO blablabla';
database.transaction(function(tx) {
database.executeSql(sqlCommand, [data.thingsToInsert], function (resultSet) {
console.log('success: insertIntoTable');
}, function (error) {
console.log('SELECT error: ' + error.message);
});
}, function(error) {
console.log('transaction error: ' + error.message);
database.close();
}, function() {
console.log('transaction ok: insertIntoTable');
});
};
app.js
ionic.Platform.ready(function () {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
};
if(window.StatusBar) {
StatusBar.styleDefault();
}
db = window.sqlitePlugin.openDatabase({name: 'myDbName.db', location: 'default'});
if (window.Connection) {
if (navigator.connection.type !== Connection.NONE) {
databaseFactory.createTables(db);
MyService.getStuffFromAPI().then(function(result) {
for (var index = 0; index < result[0].campaigns.length; index++) {
databaseFactory.insertIntoTable(db, result[0].campaigns[index]);
}
var selectResult = databaseFactory.selectFromCampaigns();
console.log(selectResult); //This log comes earlier than the above inserts could finish.
}, function(result) {
console.log(result);
});
}
}
});
The INSERT is working fine anyways, I did check it.
I know that the datebase.transaction is asynchronous so also tried it with single db.executeSQL command but had the same problem even with adding $q resolve, reject to the factory. I really could use some help, thanks!
Every Insert returns a promise. Keep those promises in an array of promises and use $q.all to wait for all of them to complete.
Example: Factory method used to insert an object
function insert(object){
var deferred = $q.defer(); //IMPORTANT
var query = "INSERT INTO objectTable (attr1, attr2) VALUES (?,?)";
$cordovaSQLite.execute(db, query, [object.attr1, object.attr2]).then(function(res) { //db object is the result of the openDB method
console.log("INSERT ID -> " + res.insertId);
deferred.resolve(res); //"return" res in the success method
}, function (err) {
console.error(JSON.stringify(err));
deferred.reject(err); //"return" the error in the error method
});
return deferred.promise; //the function returns the promise to wait for
}
And then, in every insert:
promises.push(yourService.insert(obj).then(function(result){ //"result" --> deferred.resolve(res);
//success code
}, function(error){ //"error" --> deferred.reject(err);
//error code
}));
And finally:
$q.all(promises).then(function(){//do your selects}, function(err){//error!});
Hope it helps.
More info about $q and $q.all: https://docs.angularjs.org/api/ng/service/$q#all
And another example: https://www.jonathanfielding.com/combining-promises-angular/
The problem was the way I used the database.transaction(function (tx){}) since it's itself an asynchronous function and inside the function body I can make the synchronous CRUD operations and they will happen in order.
app.js (fixed)
ionic.Platform.ready(function () {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
};
if(window.StatusBar) {
StatusBar.styleDefault();
}
db = window.sqlitePlugin.openDatabase({name: 'MagicalWonder.db', location: 'default'});
if (window.Connection) {
if (navigator.connection.type !== Connection.NONE) {
MyService.getMyPreciousData().then(function(result) {
db.transaction(function(tx) {
databaseFactory.createTable(tx);
for (var index = 0; index < result[0].campaigns.length; index++) {
databaseFactory.insertIntoTable(tx, result[0].myPreciousData[index]);
}
// HERE I CAN MAKE THE SELECT REQUESTS
}, function(error) {
console.log('transaction error: ' + error.message);
database.close();
}, function() {
console.log('transactions successfully done.');
});
}, function(result) {
console.log(result);
});
}
}
});
factory method (fixed)
factory.insertIntoTable = function (tx, data) {
var sqlCommand = 'INSERT INTO wanders (' +
'id, ' +
'magic_spell) values (?,?)';
tx.executeSql(sqlCommand, [data.id, data.magic_spell], function (tx, resultSet) {
console.log('Success: insertIntoBookOfWonder');
}, function (tx, error) {
console.log('SELECT error: ' + error.message);
});
};
I tested my app in the iOS emulator and noticed that the gps does not work.
In the emulator I set the location to "Apple"
and installed the corodova plugin by: "cordova plugin add org.apache.cordova.geolocation".
Here is my Code:
angular.module('home', ['services'])
.controller('homeCtrl',
function ($scope, $location, $state, serverAPI, $ionicPopup) {
$scope.buttonType = "icon ion-search";
$scope.buttonDisable = false;
$scope.text = 'Search';
var UID = JSON.parse(window.localStorage.getItem('Credentials')).UID;
serverAPI.getUserData(UID, function (data) {
$scope.userName = data.userName;
$scope.points = data.points;
$scope.fotoId = data.fotoId;
console.log(data);
});
$scope.click = function () {
$scope.buttonDisable = true;
$scope.text = 'Searching';
$scope.buttonType = 'icon ion-loading-a';
// //Grap geoLocation
var location = navigator.geolocation.getCurrentPosition(saveGeoData, onError);
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
};
var saveGeoData = function (geoData) {
console.log("nach geo");
var myPosition = {
'longitude': geoData.coords.longitude,
'latitude': geoData.coords.latitude
};
console.log("ss");
console.log(myPosition.latitude);
window.localStorage.setItem('myPosition', JSON.stringify(myPosition));
//If geoloaction is saved successfully => Send geodata to server to receive teammate
sendToServer(myPosition);
}
//Send current location to Server to receive teammate
var sendToServer = function (myPosition) {
serverAPI.searchPartnerToPlayWith(myPosition.longitude, myPosition.latitude, UID, function (data) {
//No other players around you. Server returns -1
if (data == -1) {
$ionicPopup.alert({
title: 'Too bad :(',
template: 'Unfortunateley there are no other players around you. Try it some other time!'
});
} else {
window.localStorage.setItem('teammate', data.username);
window.localStorage.setItem('isEnummeration', data.taskType);
window.localStorage.setItem('task', data.task);
var teammatePosition = {
'longitude': data.longitude,
'latitude': data.latitude
};
window.localStorage.setItem('teammatePosition', teammatePosition);
//TODO: data.fotoId => request foto from server
$state.go('tab.play-screen');
}
})
}
};
})
When the function click is called, it just stops in Line:
var location = navigator.geolocation.getCurrentPosition(saveGeoData, onError);
Do you have a guess whats my problem? In the browser it works just fine.
Thanks!
Make sure you include this file into your project.
https://github.com/apache/cordova-plugin-geolocation/blob/master/www/geolocation.js
It can be high probability cause from there, this function not exist in your project, getCurrentPosition.
I have a service that includes:
newStatusEvent = function(account, eventId, url, deferred, iteration) {
var checkIteration;
checkIteration = function(data) {
if (iteration < CHECK_ITERATIONS && data.Automation.Status !== 'FAILED') {
iteration++;
$timeout((function() {
return newStatusEvent(account, eventId, url, deferred, iteration);
}), TIME_ITERATION);
} else {
deferred.reject('failure');
}
};
url.get().then(function(data) {
if (data.Automation.Status !== 'COMPLETED') {
checkIteration(data);
} else {
deferred.resolve('complete');
}
});
return deferred.promise;
};
runEventCheck = function(account, eventId, modalInstance, state) {
newStatusEvent(account, eventId, urlBuilder(account, eventId),
$q.defer(), 0)
.then(function() {
scopeMutateSuccess(modalInstance, state);
}, function() {
scopeMutateFailure(modalInstance);
})["finally"](function() {
modalEventConfig.disableButtonsForRun = false;
});
};
var modalEventConfig = {
disableButtonsForRun: false,
statusBar: false,
nodeStatus: 'Building',
statusType: 'warning'
}
function scopeMutateSuccess(modalInstance, state){
/////////////////////////////////////////////////
//THE SCPOPE DATA MEMBERS THAT ARE CHANGED BUT
//CURRENT DIGEST() DOES NOT INCLUDE THE CHANGE
modalEventConfig.statusType = 'success';
modalEventConfig.nodeStatus = 'Completed Successfully';
//////////////////////////////////////////////////
$timeout(function() {
scopeMutateResetValues();
return modalInstance.close();
}, TIME_CLOSE_MODAL);
state.forceReload();
}
modalEventConfig.scopeMutateStart = scopeMutateStart;
modalEventConfig.close = scopeMutateResetValues;
return {
runEventCheck: runEventCheck,
modalEventConfig: modalEventConfig
};
And here is the controller:
angular.module('main.loadbalancer').controller('EditNodeCtrl', function($scope, $modalInstance, Configuration, LoadBalancerService, NodeService, StatusTrackerService, $state, $q) {
NodeService.nodeId = $scope.id;
$q.all([NodeService.getNode(), LoadBalancerService.getLoadBalancer()]).then(function(_arg) {
var lb, node;
node = _arg[0], lb = _arg[1];
$scope.node = node;
return $scope.save = function() {
$scope.modalEventConfig.scopeMutateStart();
return NodeService.updateNode({
account_number: lb.customer,
ip: node.address,
port: node.port_number,
label: node.label,
admin_state: node.admin_state,
comment: node.comment,
health_strategy: {
http_request: "" + node.healthMethod + " " + node.healthUri,
http_response_accept: "200-299"
},
vendor_extensions: {}
}).then(function(eventId) {
return StatusTrackerService.runEventCheck(lb.customer, eventId,
$modalInstance, $state);
});
}
});
$scope.modalEventConfig = StatusTrackerService.modalEventConfig;
The issue I am having is in the service. After a successful resolve in newStatusEvent and scopeMutateSuccess(modalInstance, state); runs... the modalEventConfig.statusType = 'success'; and modalEventConfig.nodeStatus = 'Completed Successfully'; changes aren't reflected in the view.
Normally, this would be because a digest() is needed to make angular.js aware of a change. However, I have verified in the stack(chromium debugger) that a digest() was called earlier in the stack and is still in effect when the scope members are mutated in function scopeMutateSuccess(modalInstance, state);
What is weird, if I add $rootScope.$apply() after modalEventConfig.nodeStatus = 'Completed Successfully';...then Angular.js will complain a digest() is already in progress...BUT...the view will successfully update and reflect the new changes in from the scope members nodeStatus and statusType. But, obviously this is not the answer/appropriate fix.
So, the question is why isn't the digest() that is currently running from the beginning of the stack(stack from chromium debugger) making angular.js aware of the scope changes for modalEventConfig.statusType = 'success' and modalEventConfig.nodeStatus = 'Completed Successfully'? What can I do to fix this?
$scope.modalEventConfig = StatusTrackerService.modalEventConfig; is a synchronous call, you need treat things asynchronously .
You need wait on promise(resolved by service) at calling area also, i.e. in the controller .
Fixed it.
function scopeMutateSuccess(modalInstance, state){
/////////////////////////////////////////////////
//THE SCPOPE DATA MEMBERS THAT ARE CHANGED BUT
//CURRENT DIGEST() DOES NOT INCLUDE THE CHANGE
modalEventConfig.statusType = 'success';
modalEventConfig.nodeStatus = 'Completed Successfully';
//////////////////////////////////////////////////
$timeout(function() {
scopeMutateResetValues();
state.forceReload();
return modalInstance.close();
}, TIME_CLOSE_MODAL);
}
I am using ui-router and I do a refresh with it useing $delegate. I place state.forceReload(); in the $timeout...the scope members update as they should. I have no idea why exactly, but I am glad this painful experience has come to a end.