Angularjs/Ionic DB result with promise - angularjs

I have a simple query that I am struggling with:
.factory('Config', function($http, DB) {
var self = this;
self.setValue = function(key,value) {
console.log('setValue(value)', value);
return DB.query("UPDATE config SET value = '"+value+"' WHERE key = '"+key+"'")
.then(function(result){
return DB.fetchAll(result);
});
}
self.getValue = function(key) {
return DB.query("SELECT value FROM config WHERE key = '"+key+"'")
.then(function(result){
return DB.fetchOne(result);
});
};
return self;
})
with the following code in controller.js under the heading:
.factory('DB', function($q, DB_CONFIG) {
var self = this;
self.db = null;
(I took the init part of the function away for the sake of simplicity. Also DB is working well when inserting, getting and updating data.)
self.fetchOne = function(result) {
var output = null;
output = angular.copy(result.rows.item(0));
return output;
};
self.query = function (sql, bindings) {
bindings = typeof bindings !== 'undefined' ? bindings : [];
var deferred = $q.defer();
self.db.transaction(function (transaction) {
transaction.executeSql(sql, bindings, function (transaction, result) {
deferred.resolve(result);
}, function (transaction, error) {
deferred.reject(error);
});
});
return deferred.promise;
};
self.fetchAll = function (result) {
var output = [];
for (var i = 0; i < result.rows.length; i++) {
output.push(result.rows.item(i));
}
return output;
};
Called like so:
$scope.config.recordar = Config.getValue("recordar");
Doing a console.log returns:
I am struggling to access the value: "true" which is highlighted in BLUE in the above image.
Any leads?

$scope.config.recordar = Config.getValue("recordar");
Does not work (ala JS). It has to be called like so:
Config.getValue("recordar").then(function(data) {
$scope.config.recordar
});

I assume that you shall change your function declaration from :
self.setValue = function(key,value) {
console.log('setValue(value)', value);
return DB.query("UPDATE config SET value = '"+value+"' WHERE key = '"+key+"'")
.then(function(result){
return DB.fetchAll(result);
});
}
to
self.setValue = function(key,value) {
console.log('setValue(value)', value);
DB.query("UPDATE config SET value = '"+value+"' WHERE key = '"+key+"'")
.then(function(result){
return DB.fetchAll(result);
});
}
You will return the result of your promise, not your promise
I have changed "return DB..." to "DB..."

Related

AngularJS check object/array is empty

I've read many questions and answers, noone has helped me. I've this function:
var model = {};
var mediaReproductionApp = angular.module("mediaReproductionApp",["ui.event",'ngAnimate']);
mediaReproductionApp.run(function ($http) {
$http.get("movimenti_per_totem.json").success(function (data) {
model.items = data;
});
});
mediaReproductionApp.controller("MediaReproductionCtrl", function($scope, $http, $timeout) {
$scope.item = model;
$scope.playVideo = function(media) {
return media ? "../gallery/video/" + media : null;
}
$scope.reproductionCodeIsEmpty = function() {
return Object.keys($scope.item).length == 0;
}
$scope.endVideo = function() {
$timeout(function() {
$http.get("php/delete_record.php").success(function () {
$http.get("movimenti_per_totem.json").success(function (data) {
$scope.item.items = data;
});
});
if($scope.reproductionCodeIsEmpty()) {
prelevaDati('../json/52.json', 'spot_creator', 'sc1', modello_SC, {});
$scope.checkMediaData();
}
},1800);
}
$scope.checkMediaData = function() {
$http.get("movimenti_per_totem.json").success(function (data) {
$scope.item.items = data;
});
if($scope.reproductionCodeIsEmpty()) {
$timeout(function(){$scope.checkMediaData();},2000);
}
}
$scope.checkMediaData();
});
This is my JSON file when it is not empty:
[ {"media":"zafferano_VP8.webm"}, {"media":"amaretti_VP8.webm"}, {"media":"passata_VP8.webm"}]
It never return true when it is empty. I've tried also:
$scope.reproductionCodeIsEmpty = function() {
return $scope.item.length == 0;
}
$scope.reproductionCodeIsEmpty = function() {
return $scope.item == {};
}
$scope.reproductionCodeIsEmpty = function() {
return angular.isUndefined($scope.item) || $scope.item === null;
}
$scope.reproductionCodeIsEmpty = function() {
return angular.isUndefined($scope.item.items) || $scope.item.items === null;
}
Nothing works... can u tell me why?
Thank you!
After you added to your question:
You define model as: model.items = data;
So, you empty model is: model = { items: [] }.
That's why it isn't empty. You need to test for model.items being empty.
If you need a tested way to tell that the object is empty, I'd recommend lodash.isEmpty(). You can use it for "any Array-like values such as arguments objects, arrays, buffers, strings, or jQuery-like collections".
https://lodash.com/docs/4.15.0#isEmpty
Since I don't know what your model is, this would cover the most possible data types.
_.isEmpty(null);
// => true
_.isEmpty(true);
// => true
_.isEmpty(1);
// => true
_.isEmpty([1, 2, 3]);
// => false
_.isEmpty({ 'a': 1 });
// => false
If you want to check if object/array is empty, I use:
angular.equals({}, yourObject);
angular.equals([], yourArray);

Return value from Angular Service

Hi I do not understand why always I get empty array from this service when is invoked by my controller
angular
.module('dimecuba.services', [])
.factory('Contacts', function($cordovaContacts, $ionicPlatform) {
var contactsFound = [];
var contacts = {
all:function(){
var options = {};
options.multiple = true;
options.filter = "";
//options.fields = ['displayName'];
options.hasPhoneNumber = true;
$ionicPlatform.ready(function(){
$cordovaContacts.find(options).then(
function(allContacts){
angular.forEach(allContacts, function(contact, key) {
contactsFound.push(contact);
});
console.log("Contacts Found:" + JSON.stringify(contactsFound));
return contactsFound;
},
function(contactError){
console.log('Error');
}
);
});
}
}; //end contacts
console.log("Contacts:"+JSON.stringify(contacts));
return contacts;
});
Use return to chain promises. A return statement needs to be included at each level of nesting.
app.factory('Contacts', function($cordovaContacts, $ionicPlatform) {
var contacts = {
all:function(){
var options = {};
options.multiple = true;
options.filter = "";
options.hasPhoneNumber = true;
//return promise
return $ionicPlatform.ready().then(function() {
//return promise to chain
return $cordovaContacts.find(options)
}).then(function(allContacts){
var contactsFound = [];
angular.forEach(allContacts, function(contact, key) {
contactsFound.push(contact);
});
//return to chain data
return contactsFound;
}).catch(function(contactError){
console.log('Error');
//throw to chain error
throw contactError;
});
}
}; //end contacts
return contacts;
});
In the controller, use the promise returned.
app.controller("myCtrl", function($scope,Contacts) {
var contactsPromise = Contacts.all();
contactsPromise.then( function(contactsFound) {
$scope.contactsFound = contactsFound;
});
});

Delay loading data in Angular JS

I have code like this
(function (app) {
app.controller('productListController', productListController)
productListController.$inject = ['$scope', 'apiService', 'notificationService', '$ngBootbox', '$filter'];
function productListController($scope, apiService, notificationService, $ngBootbox, $filter) {
$scope.products = [];
$scope.page = 0;
$scope.pagesCount = 0;
$scope.getProducts = getProducts;
$scope.keyword = '';
$scope.search = search;
$scope.deleteProduct = deleteProduct;
$scope.selectAll = selectAll;
$scope.deleteMultiple = deleteMultiple;
function deleteMultiple() {
var listId = [];
$.each($scope.selected, function (i, item) {
listId.push(item.ID);
});
var config = {
params: {
checkedProducts: JSON.stringify(listId)
}
}
apiService.del('/api/product/deletemulti', config, function (result) {
notificationService.displaySuccess('Deleted successfully ' + result.data + 'record(s).');
search();
}, function (error) {
notificationService.displayError('Can not delete product.');
});
}
$scope.isAll = false;
function selectAll() {
if ($scope.isAll === false) {
angular.forEach($scope.products, function (item) {
item.checked = true;
});
$scope.isAll = true;
} else {
angular.forEach($scope.products, function (item) {
item.checked = false;
});
$scope.isAll = false;
}
}
$scope.$watch("products", function (n, o) {
var checked = $filter("filter")(n, { checked: true });
if (checked.length) {
$scope.selected = checked;
$('#btnDelete').removeAttr('disabled');
} else {
$('#btnDelete').attr('disabled', 'disabled');
}
}, true);
function deleteProduct(id) {
$ngBootbox.confirm('Are you sure to detele?').then(function () {
var config = {
params: {
id: id
}
}
apiService.del('/api/product/delete', config, function () {
notificationService.displaySuccess('The product hase been deleted successfully!');
search();
}, function () {
notificationService.displayError('Can not delete product');
})
});
}
function search() {
getProducts();
}
function getProducts(page) {
page = page || 0;
var config = {
params: {
keyword: $scope.keyword,
page: page,
pageSize: 20
}
}
apiService.get('/api/product/getall', config, function (result) {
if (result.data.TotalCount == 0) {
notificationService.displayWarning('Can not find any record.');
}
$scope.products = result.data.Items;
$scope.page = result.data.Page;
$scope.pagesCount = result.data.TotalPages;
$scope.totalCount = result.data.TotalCount;
}, function () {
console.log('Load product failed.');
});
}
$scope.getProducts();
}
})(angular.module('THTCMS.products'));
So my problem is when i loading data the application take me some time to load data.
I need load data as soon as
Is the any solution for this?
Since you are loading data via api call, there will be a delay. To handle this delay, you should display a loading screen. Once the data is loaded, the loading screen gets hidden and your main screen is visible. You can achieve this using $http interceptors.
See : Showing Spinner GIF during $http request in angular
The api-call is almost certainly causing the delay. Data may be received slowly via the api-call so you could display any sort of loading text/image to notify the use that the data is being loaded.
If u want the data ready at the time when controller inits, u can add a resolve param and pass the api call as a $promise in the route configuration for this route.

Ionic/Angular concurrent SQLite connections and writes failing

I'm fairly new to both Ionic and Angular. I'm trying to write to a SQLite database and it's intermittently successful. When I do a for loop and insert records rapidly, some succeed and some fail (without apparent error). The query execution uses promises, so multiple queries may be trying to execute concurrently. It seems that this causes a synchronization issue in SQLite - or the SQLite plugin. I've tried opening a new DB connection with every execute(), reopening the existing connection on every execute(), and I've also tried opening a connection globally in app.js once and reusing that connection. They all seem to behave the same.
A custom 'dbQuery' function is used to build queries and is chainable. The idea is that any place in my app with access to the DB service can execute a query and expect the results to flow into an "out" variable like:
var my_query_results = [];
DB.begin().select("*","table1").execute(my_query_results).then(function() {
console.log("Query complete");
});
That much works, but the problem comes from writes:
var records = [
{id:1, name:"Bob"},
{id:2, name:"John"},
{id:3, name:"Jim"},
];
for (var i = 0; i < records.length; i++) {
var obj = records[i];
var result = [];
DB.begin().debug(true).insert("table1", "(id,name)", "("+obj.id+","+ obj.name+")").execute(result).then(function () {
console.log("Inserted record", JSON.stringify(obj));
});
}
Sometimes it fails without any logged or apparent error, sometimes it succeeds. If I perform the inserts slowly over time, it seems to work without issue.
app.js
var db;
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
.run(function ($ionicPlatform, $cordovaSQLite, appConfig, $q) {
$ionicPlatform.ready(function () {
db = $cordovaSQLite.openDB({
name: appConfig.sqlite_db,
location: appConfig.sqlite_db_location
});
dbQuery = function () {
this.bDebug = false;
this.query = "";
this.result = [];
this.params = [];
this.debug = function (value) {
this.bDebug = (value === true ? true : false);
return this;
};
this.rawQuery = function (query) {
this.query = query;
return this;
};
this.insert = function (table, fields, values) {
this.query = "INSERT INTO '" + table + "' (" + fields + ") VALUES (" + values + ")";
return this;
};
this.select = function (fields, table) {
this.query = "SELECT " + fields + " FROM " + table;
return this;
};
this.delete = function (query) {
this.query = "DELETE FROM " + query;
return this;
};
this.where = function (column, expression, value) {
expression = expression || "=";
this.query += " WHERE `" + column + "` " + expression + " ? ";
this.params[this.params.length] = value;
return this;
};
this.and = function (column, expression, value) {
expression = expression || "=";
this.query += " AND '" + column + "' " + expression + " ? ";
this.params[this.params.length] = value;
return this;
};
this.execute = function (out_var) {
var self = this;
this.result = out_var;
if (this.bDebug) {
console.log("Compiled query is", this.query);
}
var deferred = $q.defer();
db.open(function () {
console.log("Opened");
}, function () {
console.log("Failed");
});
//actually execute the query
$cordovaSQLite.execute(db, this.query, this.params).then(
function (res) {
for (var i = 0; i < res.rows.length; i++) {
self.result.push(res.rows.item(i));
console.log("Added row to set", JSON.stringify(res.rows.item(i)));
}
if (res.rows.length == 0 && self.bDebug === true) {
console.log("No results found ");
}
deferred.resolve();
}, function (err) {
console.error(JSON.stringify(err), this.query);
deferred.reject();
});
return deferred.promise;
}
services.js
.factory('DB', function ($ionicPlatform) {
return {
begin: function () {
return new dbQuery();
}
}
})
.factory('DbBootstrap', function ($cordovaSQLite, appConfig, $q, $state, DB) {
return {
wipe: function () {
DB.begin().rawQuery("DELETE FROM table1").execute().then(function () {
console.log("Purged records");
});
},
init: function () {
var result = []; //out variable
DB.begin().rawQuery("CREATE TABLE IF NOT EXISTS table1 (id integer primary key, name text)").execute(result).then(function () {
console.log("Schema create returned", JSON.stringify(result));
});
var records = [
{
id: 1, name:'Jim'
...
},
{
id: 2, name:'Bob'
...
},
{
id: 3, name:'John'
...
}
];
for (var i = 0; i < records.length; i++) {
var obj = records[i];
var result = [];
DB.begin().debug(true).insert("table1", "(id,name)", "(obj.id, obj.name).execute(result).then(function () {
console.log("Inserted record", JSON.stringify(obj));
});
}
}
})
I'm sure I'm missing something fundamental about angular, promises, and sqlite locking. If anyone has advice I'd really appreciate it.
I resolved this following the excellent advice here - Angular/Ionic and async SQLite - ensuring data factory initialised before return
The key issue being that I needed to wrap all my DB operations in promises and use them for orderly initialization and callbacks.
.factory('DB', function ($q, $cordovaSQLite, appConfig) {
//private variables
var db_;
// private methods - all return promises
var openDB_ = function (dbName, location) {
var q = $q.defer();
try {
db_ = $cordovaSQLite.openDB({
name: dbName,
location: location
});
q.resolve(db_);
} catch (e) {
q.reject("Exception thrown while opening DB " + JSON.stringify(e));
}
return q.promise;
};
var performQuery_ = function (query, params, out) {
var q = $q.defer();
params = params || [];
out = out || [];
//open the DB
openDB_(appConfig.sqlite_db, appConfig.sqlite_db_location)
.then(function (db) {
//then execute the query
$cordovaSQLite.execute(db, query, params).then(function (res) {
//then add the records to the out param
console.log("Query executed", JSON.stringify(query));
for (var i = 0; i < res.rows.length; i++) {
out.push(res.rows.item(i));
console.log("Added row to set", JSON.stringify(res.rows.item(i)));
}
if (res.rows.length == 0 && self.bDebug === true) {
console.log("No results found ");
}
}, function (err) {
console.log("Query failed", JSON.stringify(query));
q.reject();
});
db_.open(function () {
q.resolve("DB Opened")
}, function () {
q.reject("Failed to open DB");
});
}, function (err) {
console.log(JSON.stringify(err), this.query);
q.reject(err);
});
return q.promise;
};
// public methods
var execute = function (query, params, out) {
var q = $q.defer();
performQuery_(query, params, out).then(function () {
q.resolve([query, params]);
}, function (err) {
q.reject([query, params, err]);
});
return q.promise;
};
return {
execute: execute
};
})

return data after a service call

I have a function which makes a service call. I have the code like below. But from success function i am unable to return the data back to calling function. How do i do this?
$scope.getData = function()
{
var successFunc = function(serverResponse)
{
if(serverResponse.header.status === "success" )
{
return serverResponse.data;
}
else
{
errorFunc("Error occured:");
}
}
var errorFunc = function(jsonResponse)
{
console.log( "Error occured:" + JSON.stringify(jsonResponse));
};
utils.svcall('abc/new', successFunc, errorFunc);
};
var data = $scope.getData();

Resources