Ionic Local Storage - save $http database to device - angularjs

I'm having some troubles with the local storage and my Ionic app. The thing is quite straight forward - I would like to store to device all the data from from sql database and then display it when the device is without network.
So the code where I get my data from looks like this:
controllers.js:
$http.get('http://someurl.php?type=json')
.success(function(data) {
$scope.info = data;
})
.error(function(response) {
$scope.info = "Error";
});
So can anyone help me out with this one?
Thank you!

I can suggest to you to use some plugin for DB but with localstorage you have to pass (and install) this:
angular-local-storage
and then use it in your JS like:
$http.get('http://someurl.php?type=json')
.success(function(data) {
//test if is online or offline and the do something
if($rootScope.isOnLine)
localStorageService.set("nameofkey", { data:data }); //here you store in your localstorage ... remeber to inject it as dependency
$scope.info = data;
})
.error(function(response) {
$scope.info = "Error";
});
then if you want to know if your ionic app is online or offline you can use this plugin: http://ngcordova.com/docs/plugins/network/
"use strict";
// Ionic Starter App
angular.module("myapp", ["ionic",
"ionic.service.core",
"ngCordova",
"ionic.service.push",
"ngResource",
"LocalStorageModule",
"ionic-native-transitions",
"angularMoment"])
.run(["$ionicPlatform", "authService", "$rootScope", "$timeout", "$cordovaSpinnerDialog", "$window", "$cordovaNetwork", "$state", "ScanService", "$cordovaToast", "localStorageService", "DB",
function ($ionicPlatform, authService, $rootScope, $timeout, $cordovaSpinnerDialog, $window, $cordovaNetwork, $state, ScanService, $cordovaToast, localStorageService, DB) {
$ionicPlatform.ready(function () {
$rootScope.isOnLine = true;
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (ionic.Platform.isIPad() &&
window.cordova &&
window.cordova.plugins &&
window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
// CONNECTION STATE /////////////////////////////////////////////
if ($cordovaNetwork) {
//listen for OnLine event
$rootScope.$on('$cordovaNetwork:online', function (event, networkState) {
var onlineState = networkState;
$rootScope.isOnLine = true;
});
// listen for Offline event
$rootScope.$on('$cordovaNetwork:offline', function (event, networkState) {
var offlineState = networkState;
$rootScope.isOnLine = false;
});
}
//////////////////////////////////////////////////////////////////
});
}]);
This is an exmaple for a Service using it for call http or from local if there is no connection:
"use strict";
angular
.module('gestione')
.factory("ScanService", ["$q", "$resource", "enviroment", "$rootScope", "localStorageService", "DB",
function ($q, $resource, enviroment, $rootScope, localStorageService, DB) {
var self = this;
// Private Fileds
var _serviceBase = "api/Scan/";
var _serviceBaseBarScan = "api/BarScan/";
var _serviceBaseCount = "api/Scan/Count";
var _serviceBaseLast = "api/Scan/Last";
var _serviceBaseAll = "api/Scan/All";
// Private Method
var _resource = $resource(enviroment.apiUrl + _serviceBase, { skip: '#skip', take: '#take' }, {
query: { method: "GET", isArray: true },
create: { method: "POST", isArray: false }
});
var _resourceLast = $resource(enviroment.apiUrl + _serviceBaseLast, {}, {
query: { method: "GET", isArray: false }
});
var _resourceAll = $resource(enviroment.apiUrl + _serviceBaseAll, {}, {
create: { method: "POST", isArray: true }
});
var _resourceCount = $resource(enviroment.apiUrl + _serviceBaseCount, {}, {
query: { method: "GET", isArray: false }
});
var _resourceBar = $resource(enviroment.apiUrl + _serviceBaseBarScan, {}, {
query: { method: "GET", isArray: true },
create: { method: "POST", isArray: false }
});
return {
Get: function (skip, take) {
var deferred = $q.defer();
// IS ONLINE
if ($rootScope.isOnLine) {
_resource.query({ skip, take }).$promise.then(function (resp) {
deferred.resolve(resp);
}).catch(function (err) {
deferred.reject(err);
});
} else { // OffLine
DB.Query("SELECT * FROM Scan ORDER BY ROWID DESC ;").then(function (result) {
var scan = DB.fetchAll(result);
deferred.resolve(scan);
}, function (err) {
deferred.reject(err);
});
}
return deferred.promise;
},
GetLast: function () {
var deferred = $q.defer();
// IS ONLINE
if ($rootScope.isOnLine) {
_resourceLast.query().$promise.then(function (resp) {
deferred.resolve(resp);
}).catch(function (err) {
deferred.reject(err);
});
} else { // OffLine
DB.Query("SELECT * FROM Scan ORDER BY ROWID DESC LIMIT 1 ;").then(function (result) {
var scan = DB.fetch(result);
deferred.resolve(scan);
}, function (err) {
deferred.reject(err);
});
}
return deferred.promise;
},
GetNotSync: function () {
return DB.Query("SELECT * FROM Scan WHERE sync = ? ", ['false']).then(function (result) {
return DB.fetchAll(result);
});
},
CheckInOrOut: function (item) {
return DB.Query("SELECT * FROM Scan WHERE idTicket = ? ORDER BY ROWID DESC LIMIT 1;", [item.IdTicket]).then(function (result) {
return DB.fetch(result);
});
},
Count: function () {
var deferred = $q.defer();
// IS ONLINE
if ($rootScope.isOnLine) {
_resourceCount.query().$promise.then(function (resp) {
deferred.resolve(resp);
}).catch(function (err) {
deferred.reject(err);
});
} else { // OffLine
DB.Query("SELECT COUNT(*) FROM Scan;").then(function (result) {
var scan = DB.fetch(result);
deferred.resolve(scan);
}, function (err) {
deferred.reject(err);
});
}
return deferred.promise;
},
Save: function (scan) {
var deferred = $q.defer();
//We're OnLine
if ($rootScope.isOnLine) {
_resource.create(scan).$promise.then(function () {
scan.sync = true;
}).catch(function () {
scan.sync = false;
}).finally(function () {
DB.Insert(scan).then(function (record) {
deferred.resolve(record);
}).catch(function () {
deferred.reject();
});
});
} else { // OffLine
scan.sync = false;
DB.Insert(scan).then(function (record) {
deferred.resolve(record);
}).catch(function () {
deferred.reject();
});
}
return deferred.promise;
},
Sync: function () {
var self = this;
var deferred = $q.defer();
var allPromise = [];
//get all stored scans
self.GetNotSync().then(function (scanList) {
// send them to the server
if (scanList && scanList.length > 0)
_resourceAll.create(scanList).$promise.then(function (resp) {
//cicle on each record returned from server
resp.forEach(function (item) {
if (item) {
//prepare query
var update_query = "UPDATE Scan SET sync= 'true' WHERE idTicket= " + item.idTicket;
//set sync to true on records
allPromise.push(DB.Update(update_query));
}
});
}).catch(function (err) {
allPromise.push(deferred.reject(err));
});
}).catch(function (error) { allPromise.push(deferred.reject(error)); });
return $q.all(allPromise);
},
GetBarScan: function () {
return _resourceBar.query();
},
SaveBarScan: function (barscan) {
var deferred = $q.defer();
_resourceBar.create(barscan).$promise.then(function (record) {
deferred.resolve(record);
}).catch(function () {
deferred.reject();
});
return deferred.promise;
}
};
}
]);

Related

AngularJS 1.7 - HTTP POST

Upgrade to angularjs version 1.7 and this code does not compile
app.factory('LoginService', function ($http) {
return {
login: function (param, callback) {
$http.post(url, param)
.success(callback)
.error(function (data, status, headers, config) {
});
}
};
});
On the controller I make the call to the service LoginService
function LoginController($http, $location, LoginService, blockUI) {
var vm = this;
LoginService.usuario(
{login: vm.username, clave: vm.password},
function (data, status, headers, config) {
vm.resultado = data;
if (vm.resultado == "True") {
window.location = "/Home/Index";
} else {
vm.error = 'Usuario o password incorrecto';
}
});
};
I want to know how the function is called from the controller because it implemented the http.post service using .then
app.factory('LoginService', function ($http) {
return {
login: function (data) {
$http.post(url, data)
.then(function (resultado) {
debugger;
if (resultado.data === "True") {
return resultado.data;}
else {
console.log("NO");}
});
}};
});
I suggest you get familiar with a AngularJS $q service and its Promise API.
You LoginService.login(...) method should return the Promise from $http.post(...):
app.factory('LoginService', function ($http) {
return {
login: function (data) {
return $http.post(url, data)
.then(function(response) {
return response.data;
});
});
Then, your Controller can access the returned data via the resolved Promise:
function LoginController(LoginService) {
var vm = this;
LoginService.login({login: vm.username, clave: vm.password})
.then(function (result) {
// handle result here...
});
the solution would be this:
function LoginController($scope,$window,$q,LoginService) {
$scope.fnBusqueda = function () {
var promesas = [
obtenerLogin()
];
$q.all(promesas).then(function (promesasRes) {
var oArrayResponse = promesasRes;
if ((oArrayResponse.length > 0)) {
$scope.respuesta = oArrayResponse[0];
if ($scope.respuesta == "True") {
window.location = "/Home/Index";
} else {
$cope.error = 'Usuario o password incorrecto';
}
}
});
};
function obtenerLogin() {
var defered = $q.defer();
var promise = defered.promise;
LoginService.login(url_valida_login, '{login:X,clave:X}').then(function (response) {
defered.resolve(response);
}).catch(function (data) {
defered.resolve([]);
})
return promise;
}
}

Is there a way to get the real data for karma unit tests with services?

I would like to test an angular service - e.g.:
'use strict';
angular
.module('com.attributes.services', [])
.service('krAdminAttributeService', [
'$rootScope',
'$http',
function ($rootScope, $http) {
var modelData = {
"type": "",
"groupId": "",
"unit": "",
"description": "",
"name": {}
};
var service = {
mapAttributes: function (results, update) {
if (!update) {
modelData.identifier = results.identifier;
}
modelData.type = results.type;
modelData.groupId = results.groupselect;
if (results.unit !== undefined) {
modelData.unit = results.unit;
}
modelData.description = results.description;
//Name
modelData.name = {
i18n: true,
key: "klapi.attribute:" + results.identifier + ".name"
};
modelData = angular.copy(modelData);
},
get: function (params) {
//return the promise directly.
return $http.get($rootScope.globals.API + 'Attributes', {params: params}).then(function (result) {
return result.data;
});
},
getId: function (id) {
//return the promise directly.
return $http.get($rootScope.globals.API + 'Attributes/' + id + "?filter[include]=group").then(function (result) {
return result.data;
});
},
update: function (results) {
this.mapAttributes(results, true);
return $http.put($rootScope.globals.API + "Attributes/" + results.id, JSON.stringify(modelData), $rootScope.globals.CONFIG).then(function (result) {
return result;
});
},
updateName: function (params) {
return $http({
method: 'POST',
url: $rootScope.globals.I18NAPI + "change/de/klapi.attribute",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: params
}).then(function (result) {
return result;
});
},
add: function (results) {
this.mapAttributes(results, false);
return $http.post($rootScope.globals.API + "Attributes", JSON.stringify(modelData), $rootScope.globals.CONFIG).then(function (result) {
return result;
});
},
delete: function (id) {
// post(url, data, [config]);
return $http.delete($rootScope.globals.API + "Attributes/" + id, $rootScope.globals.CONFIG).then(function (result) {
return result;
});
}
};
return service;
}]);
My test looks like this:
describe("krAdminAttributeService", function () {
var krAdminAttributeService,
$q,
rootScope,
httpBackend;
beforeEach(function () {
module('app');
inject(function($httpBackend, _krAdminAttributeService_, _$q_, $rootScope) {
krAdminAttributeService = _krAdminAttributeService_;
httpBackend = $httpBackend;
rootScope = $rootScope.$new();
$q = _$q_;
});
});
// check to see if it has the expected function
it('should have a get function', function () {
expect(angular.isFunction(krAdminAttributeService.get)).toBe(true);
});
it('should have a getId function', function () {
expect(angular.isFunction(krAdminAttributeService.getId)).toBe(true);
});
it('should have an update function', function () {
expect(angular.isFunction(krAdminAttributeService.update)).toBe(true);
});
it('should get the attributes', function () {
var data;
var response = {id:"12345"};
httpBackend.whenGET('http://localhost:3000/api/Attributes').respond(200,response);
// set up a deferred
var deferred = $q.defer();
// get promise reference
var promise = deferred.promise;
// set up promise resolve callback
promise.then(function (response) {
console.log('data',response);
data = response;
});
krAdminAttributeService.get().then(function(response) {
// resolve our deferred with the response when it returns
deferred.resolve(response);
console.log('response', response);
});
httpBackend.flush();
// make your actual test
//expect(data).toEqual(200);
});
});
The problem is, that this unit test is not retrieving the actual data but just some mocked data (in this case {id:'12345'}). For me, that makes the test less useful. Is there a way to test with real data? (CORS available)

While returning promise it gives me an unknown provider error

This the factory.
latModule.factory('latSvc',
[
"$http", "$scope", "$q",
function($http, $scope, $q) {
console.log("Enter latUserReportDateSvc");
return {
getPromiseForUserReportDate: function () {
$scope.userId = "bpx3364";
var deferred = $q.defer();
$http.get('/api/UserReportStatusApi', { 'userId': $scope.userId }).then(function(reponse) {
deferred.resolve(reponse);
},
function(error) {
deferred.reject(error);
});
return deferred.promise;
},
getPromiseForLocation: function () {
$scope.userId = "bpx3364";
var deferred = $q.defer();
$http.get('api/UserAccountApi/', { 'userId': $scope.userId }).then(function (reponse) {
deferred.resolve(reponse);
},
function (error) {
deferred.reject(error);
});
return deferred.promise;
},
getPromiseForErrorSummary: function (userInfoVm) {
console.log("latErrorSummarySvc getErrorCounts, userInfo: ", userInfoVm);
$scope.userId = "bpx3364";
$scope.serviceTypeCode = 4;
var deferred = $q.defer();
$http.get('/api/UserReportStatusApi', { 'userId': $scope.userId, 'serviceTypeCode': $scope.serviceTypeCode }).then(function (reponse) {
deferred.resolve(reponse);
},
function (error) {
deferred.reject(error);
});
return deferred.promise;
}
};
}
]);
This is the controller
latModule.controller("dashboardController",
["$scope","latSvc",
function ($scope,latSvc) {
console.log("enter dashboard controller");
console.log("scope: ", $scope);
console.log("homeUserInfo: ", $scope.homeLatUserInfo);
var dashboardUserReportDate = function() {
latSvc.getUserReportDateInfo().then(
function(response) {
$scope.dashboardUserReportDateData = response;
}, function(error) {}
);
};
dashboardUserReportDate();
var dashboardErrorCounts = function() {
latSvc.getPromiseForErrorSummary($scope.homeLatUserInfo).then(
function(response) {
$scope.dashboardErrorCountsData = response;
},
function (error) { }
);
};
dashboardErrorCounts();
var dashboardAtmCount = function() {
latSvc.getPromiseForLocation().then(
function(response) {
$scope.dashboardAtmCountData = response;
}, function(error) {}
);
};
dashboardAtmCount();
}]);
after running this code I am getting an unknown provider error while I am trying to implement this promise concept.Because while I was calling through service with out resolving promise and without using then the url was getting hit multiple times.
You can't use / inject $scope into a service.
But as far as I understand your code you should be fine using local variables for your http request query parameters.
And Vineet is right - you should return the $http.get() directly (it's already a promise).

The correct definition of data

i have this code, when i run it i get an error of "ReferenceError: data is not defined" i have defined data in several ways but nothing seem to be correct. the thing is that when i think about it data is declared in api (no?).. would appreciate some help..
app.service('StatisticsService',
['apiClient', '$q', '$rootScope', '$timeout',
function (apiClient, $q, $rootScope, $timeout) {
var self = this;
self.getStatisticsFromServer = function (data) {
var deferred = $q.defer(); //1
apiClient.getStatsTopMeeters(data)
.then(function (response) { //2
console.log('externalApiConnect', response);
if (response.data.length === 0 || response.result !== "success") {
// TODO: show error
deferred.reject(response);
}
var stats = response.data;
stats = self.getUserProfiles(stats);
deferred.resolve(stats);//3
}
, function (error) {
deferred.reject(error);
console.error(error);
});
return deferred.promise; //4
};
self.getUserProfiles = function (stats) {
var deferred = $q.defer();
var emails = [];
for (var i = 0; i < stats.length; i++) {
emails.push(stats[i].email);
}
console.log(emails);
var data2 = {
token: data.token,
profile_emails: emails
};
apiClient.getUserProfiles(data2).then(function (response2) {
console.log('getUserProfiles', (response2));
if (response2.data.length === 0 || response2.result !== "success") {
// TODO: show error
deferred.reject(response2);
}
var stats = response2.data;
deferred.resolve(stats);//3
}
);
};
}]);
this is some of the apiClient page
app.service('apiClient', ['$http', '$q','$rootScope', function ($http, $q, $rootScope) {
var canceler = $q.defer();
var request = function (apiMethod, apiResponse) {
switch (apiMethod) {
case 'set_meeting_note':
case 'get_meeting_details':
case 'get_account_details':
case 'get_availability':
case 'get_best_time':
case 'get_participants_statuses':
case 'check_user_verified_send_email':
case 'get_participants_statuses':
case 'get_user_profiles':
case 'set_calendar_settings':
case 'sync_external_apis':
$rootScope.showLoader = false;
break;
default:
$rootScope.showLoader = true;
break;
}
var config = {
method: 'POST',
url: apiPath + apiMethod,
data: apiResponse,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
withCredentials: true,
timeout: canceler.promise
};
$http(config).success(function (data) {
$rootScope.showLoader = false;
if (data.message === undefined) {
deferred.resolve(data);
} else {
deferred.reject(data);
}
}).error(function (data, status, headers, config) {
$rootScope.showLoader = false;
deferred.reject(data);
});
return deferred.promise;
};
return {
getStatsTopMeeters: function (data) {
return request('get_stats_top_meeters',data );
},
getUserProfiles: function(data){
return request('get_user_profiles',data);
},
}

Storing tokens with OAuth 2.0 in Angular

I have an app which displays Google Calendar data, but it requires an initial login. I know it's possible to store tokens using OAuth 2.0, but I'm not sure how to go about doing it. Here is my code below. I'd like for the webpage to display the a calendar using JSON data from a google calendar without login.
Controller
angular.module('demo', ["googleApi"])
.config(function(googleLoginProvider) {
googleLoginProvider.configure({
clientId: '239511214798.apps.googleusercontent.com',
scopes: ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/plus.login"]
});
})
.controller('DemoCtrl', ['$scope', 'googleLogin', 'googleCalendar', 'googlePlus', function ($scope, googleLogin, googleCalendar, googlePlus) {
$scope.login = function () {
googleLogin.login();
};
$scope.$on("googlePlus:loaded", function() {
googlePlus.getCurrentUser().then(function(user) {
$scope.currentUser = user;
});
})
$scope.currentUser = googleLogin.currentUser;
$scope.loadEvents = function() {
this.calendarItems = googleCalendar.listEvents({calendarId: this.selectedCalendar.id});
}
$scope.loadCalendars = function() {
$scope.calendars = googleCalendar.listCalendars();
}
}]);
googleAPi
angular.module('googleApi', [])
.value('version', '0.1')
.service("googleApiBuilder", function($q) {
this.loadClientCallbacks = [];
this.build = function(requestBuilder, responseTransformer) {
return function(args) {
var deferred = $q.defer();
var response;
request = requestBuilder(args);
request.execute(function(resp, raw) {
if(resp.error) {
deferred.reject(resp.error);
} else {
response = responseTransformer ? responseTransformer(resp) : resp;
deferred.resolve(response);
}
});
return deferred.promise;
}
};
this.afterClientLoaded = function(callback) {
this.loadClientCallbacks.push(callback);
};
this.runClientLoadedCallbacks = function() {
for(var i=0; i < this.loadClientCallbacks.length; i++) {
this.loadClientCallbacks[i]();
}
};
})
.provider('googleLogin', function() {
this.configure = function(conf) {
this.config = conf;
};
this.$get = function ($q, googleApiBuilder, $rootScope) {
var config = this.config;
var deferred = $q.defer();
return {
login: function () {
gapi.auth.authorize({ client_id: config.clientId, scope: config.scopes, immediate: false}, this.handleAuthResult);
return deferred.promise;
},
handleClientLoad: function () {
gapi.auth.init(function () { });
window.setTimeout(checkAuth, 1);
},
checkAuth: function() {
gapi.auth.authorize({ client_id: config.clientId, scope: config.scopes, immediate: true }, this.handleAuthResult );
},
handleAuthResult: function(authResult) {
if (authResult && !authResult.error) {
var data = {};
$rootScope.$broadcast("google:authenticated", authResult);
googleApiBuilder.runClientLoadedCallbacks();
deferred.resolve(data);
} else {
deferred.reject(authResult.error);
}
},
}
};
})
.service("googleCalendar", function(googleApiBuilder, $rootScope) {
var self = this;
var itemExtractor = function(resp) { return resp.items; };
googleApiBuilder.afterClientLoaded(function() {
gapi.client.load('calendar', 'v3', function() {
self.listEvents = googleApiBuilder.build(gapi.client.calendar.events.list, itemExtractor);
self.listCalendars = googleApiBuilder.build(gapi.client.calendar.calendarList.list, itemExtractor);
self.createEvent = googleApiBuilder.build(gapi.client.calendar.events.insert);
$rootScope.$broadcast("googleCalendar:loaded")
});
});
})
.service("googlePlus", function(googleApiBuilder, $rootScope) {
var self = this;
var itemExtractor = function(resp) { return resp.items; };
googleApiBuilder.afterClientLoaded(function() {
gapi.client.load('plus', 'v1', function() {
self.getPeople = googleApiBuilder.build(gapi.client.plus.people.get);
self.getCurrentUser = function() {
return self.getPeople({userId: "me"});
}
$rootScope.$broadcast("googlePlus:loaded")
});
});
})
What you will want to do is after the result comes back you will want to save it off to localStorage or a cookie and then use that in the future if it exists.
Essentially you will need to update your handleAuthResult to store the result from the Google API:
handleAuthResult: function (authResult) {
if (authResult && !authResult.error) {
var data = {};
$rootScope.$broadcast("google:authenticated", authResult);
googleApiBuilder.runClientLoadedCallbacks();
// here you will store the auth_token
window.localStorage.setItem('auth_token', authResult.token /*I don't know what this response looks like, but it should be similar to this*/ );
deferred.resolve(data);
} else {
deferred.reject(authResult.error);
}
},
Live Demo

Resources