I am using ionic framework .
I am implementing following steps
1) As my app runs . it will create db and table
2) As soon as use login, i am saving data into mysql and go to Dashboard page
dbQuery.insertCategory();
$state.go('app.dashboard');
dbQuery is factory .
.factory('dbQuery', function ($http, $q, $cordovaSQLite, localstorage) {
return {
insertCategory: function () {
$http({
url: "http://mydoman.comcategory",
method: 'GET',
withCredentials: true,
}).success((function (result) {
var user_id = localstorage.get('user_id');
var query = "INSERT OR IGNORE INTO categories (category_id, user_id, category_name,category_type) VALUES (?,?,?,?)";
var data = '';
result.forEach(function (category) {
$cordovaSQLite.execute(db, query, [category.id,user_id, category.category_name, category.category_type]).then(function (res) {
console.log("insertId");
}, function (err) {
console.dir(err);
});
});
}))
},
Which is working fine
On Dashboard i am showing categories list and i found nothing .
I did debugging and found insertion of categories taking time to insert.
Is there is any way to do two way data binding
Thanks
Why not use a promise and only redirect to app.dashboard once the success promise triggers?
Example:
dbQuery.insertCategory().then(function(result) {
$state.go('app.dashboard');
}, function(error) {
console.error(error);
});
Then in your factory you can have something like this:
.factory('dbQuery', function ($http, $q, $cordovaSQLite, localstorage) {
return {
insertCategory: function () {
var deferred = $q.defer();
$http({
url: "http://mydoman.comcategory",
method: 'GET',
withCredentials: true,
}).success((function (result) {
var user_id = localstorage.get('user_id');
var query = "INSERT OR IGNORE INTO categories (category_id, user_id, category_name,category_type) VALUES (?,?,?,?)";
var data = '';
result.forEach(function (category) {
isWaiting = true;
$cordovaSQLite.execute(db, query, [category.id,user_id, category.category_name, category.category_type]).then(function (res) {
console.log("insertId");
isWaiting = false;
}, function (err) {
console.dir(err);
isWaiting = false;
});
while(isWaiting) {}
});
deferred.resolve("done");
}))
return deferred.promise;
},
A lot of what I did is just theory, but it should give you an idea. I created a boolean to make the SQL commands synchronous. Since they are synchronous, when the loop ends, you can return your success promise.
There are probably a few other ways you could do it as well. Like maybe move the SQL stuff into its own function and recursively enter it.
Let me know if any of this works for you.
Related
In the following code I want to execute a series of $http requests that modify a list. When all the responses are received, I want to process the list and remove part of the content.
The problem is that when I print the list after $q.all, the Chrome console shows a length of 3, but when I expand it to read the content only 2 elements are shown. On JSFiddle I have no issues, though.
var app = angular.module('MyApp',[]);
app.controller('MyController',['$scope','$q',"$http", function($scope,$q,$http){
var loopPromises = [];
var workorders = null;
$scope.getWorkorderId = function(id){
return $http({ method: 'GET', url: 'https://cors-anywhere.herokuapp.com/https://blk.clojure.xyz/interdiv/api/v1/service/' + id })
.then(function success(response) {
return response.data;
}, function error(response) {
console.log(response);
});
}
$http({ method: 'GET', url: 'https://cors-anywhere.herokuapp.com/https://blk.clojure.xyz/interdiv/api/v1/workorder' })
.then(function success(response) {
workorders = response.data;
}, function error(response) {
console.log(response);
})
.then(function() {
if (workorders == null) {
return;
}
angular.forEach(workorders, function(value, index, obj) {
var deferred = $q.defer();
loopPromises.push(deferred.promise);
var waitResponse = $scope.getWorkorderId(value.id);
waitResponse
.then(function(res) {
obj[index].services = res;
deferred.resolve();
})
});
$q.all(loopPromises)
.then(function() {
// Should contain 3 elements, only 2 are shown
console.log(workorders);
});
});
}]);
see better in the screenshots. Console Requests
The problem was in the second part of the code not copied in the question: I was using .splice() inside angular.forEach() which changes the indices of the elements within the array.
I am working on blogging app . i want to save article list on SqlLite as well. I need to fetch all blogs in once. ( having more than 2000) blogs .
following is my controller code.
var promise= userService.getArticles();
promise.then(function(data) {
$scope.articles = data;
}, function(error) {
console.log('Failed for some reason:' + error);
});
and factory code is
angular.module('starter.controllers')
.factory('userService', function($http,$q) {
var articleList = [];
return {
getArticles : function() {
var deferred = $q.defer();
$http({
url: "https://www.website.com/getallinfo?access_token=94529e5d",
data: { starLimit: 0, endLimit: 150,created_date: 0 },
method: 'POST',
withCredentials: true,
}).success(function (data, status, headers, config) {
deferred.resolve(data);
}).error(function (err) {
deferred.reject(error); //
})
return deferred.promise;
},
}
which is returing result.
I need to save that data in sqllite as well. Also i want to show data as offline.
I am not sure how to proceed this. Kindly help.
Thanks
Most offline applications use the local storage as a cache and updating that if there's a connection available.
An easy way to do this is to:
Grab the articles from the local storage and assign it to a $scope variable (this can be undefined)
Request the articles as normal from the server
On a successful callback overwrite the local storage and reassign the scope variable.
Exampe code:
// The article service
myApp.factory('articles', function($q, $timeout, $window, loremIpsum) {
// Initialize by grabbing the articles from the local cache (if any)
var items = angular.fromJson($window.localStorage.getItem('myArticles'));
// Construct our service
var service = {
items: items,
refresh: function() {
// Sync with the server
var defer = $q.defer();
// For this demo I'm using a timeout (this also allows for some artificial lag).
// Replace this with your $http calls.
$timeout(function() {
// Here I'm generating some total random items that we're resolving
// Also not needed in your app
var c = 100, result = [];
while (c--) {
result.push({
title: loremIpsum.getRandomLine(2),
description: loremIpsum.getRandomLine(15)
});
}
service.items = result;
defer.resolve(result);
// Store the returned result from the server in the local storage
$window.localStorage.setItem('myArticles', angular.toJson(result));
}, 500);
return defer.promise;
}
};
return service;
});
Plunker example can be found here.
I have a model that I am using to hold my data in angular:
var FuelProcessingModel = function (carrierService) {
this.myArray = [];
};
That model has an array of MyObjects that I get from the DB:
var MyObject = function () {
//stuff
}
I update this using a REST call:
$scope.add = function () {
var myObject = new MyObject();
$scope.model.MyObjects.push(myObject);
service.add(myObject);
};
Which I use a service to hit the Server:
this.add = function (myObject) {
$http({
method: "POST",
url: "theServer",
data: myObject
});
}
The REST service just adds to the database, It doesn't return anything.
I need to reload the data from the database after the update is finished, so that my records now have all newly associated ID's and pertinent data.
I cannot just do:
window.location.reload();
The user starts by selecting a value from a drop down list to decide which list of data they start off seeing. I cannot / do not want to pass the value to it, mainly because it is in its own partial view, with its own controller, because it is used on many pages.
I tried doing:
$scope.add = function () {
//same as above
//this
service.get().then(function(result) { $scope.model.myArray = result.data; });
};
Obviously the problem here is the promise isn't complete before the DOM reloads the page. So the user saw themself add an item to the array and it vanished.
Do I want to load the page after the promise is complete? (How would I do that?)
should I return the updated data from the REST service and reset the current value? (seems like the same promise issue)
Is there a better practice that I do not know about?
UPDATE
For Bergi:
this.get = function (key) {
return $http({
method: "GET",
url: "theServer" + key
})
.success(function (data) {
return data;
});
}
I think you want to chain your two promises:
$scope.add = function () {
var myObject = new MyObject();
$scope.model.MyObjects.push(myObject);
return service.add(myObject).then(function() {
return service.get();
}).then(function(result) {
$scope.model.myArray = result.data;
});
};
and
this.add = function(myObject) {
return $http({
// ^^^^^^ return a promise here
method: "POST",
url: "theServer",
data: myObject
});
};
You can wrap your service call in a deferred promise, and on return success re-init your data from the controller..
$scope.add = function () {
var myObject = new MyObject();
$scope.model.MyObjects.push(myObject);
service.add(myObject).then(function (response) {
// here's where you'd do whatever you want to refresh your model
}),
function (err) {console.log(err);};
};
And the service:
this.add = function (myObject) {
var deferred = $q.defer();
$http({
method: "POST",
url: "theServer",
data: myObject,
success: function (response) {
deferred.resolve(err);
},
error: function (err) {
deferred.reject(err);
}
});
return deferred.promise;
}
I have this service:
angular.module('autotestApp').factory('GroupService', ['$http', function ($http) {
var groups = [];
return{
list: function () {
return groups;
},
retrieve: function () {
$http({
method: "get",
url: "/enterprises/_groups"
}).success(function (response) {
groups = response;
}).error(function () {
console.log("failed")
});
}
}
}]);
and this is my controller:
angular.module('autotestApp').controller('GroupsController', function($scope, $http, GroupService) {
GroupService.retrieve();
$scope.items = GroupService.list();
});
So, in my controller, I am first getting the result from the API so that the variable groups(in the service) gets assigned, then I am using the list() method to assign the values to $scope.items.
I am sure that API is returning results. But the
groups = response
part is not working correctly. When I changed it to
groups.push(response)
it is working but the result is a list inside a list, which I dont't want: [[ Object, Object, Object ]]
I want this: [ Object, Object, Object ]
How to fix this?
The reason
groups = response
is not working is because you're sending an async request that will replace the groups reference after you've already retrieved the old reference via the list function. The reason it works with the push modification is because Angular creates a watch that notices that the collection has changed and updates your view. However, your code is now working, but you don't understand why it works, and it's prone to breaking unexpectedly.
When dealing with asynchronous code, the best way to deal with it is to write your own code to take that into account. Here's a version that does the whole thing in an async fashion:
angular.module('autotestApp').factory('GroupService', ['$http', function ($http) {
var groupsResult;
return{
retrieve: function () {
if (groupsResult) { return groupsResult; }
return groupsResult = $http({
method: "get",
url: "/enterprises/_groups"
}).then(function (response) {
return response.data;
}, function () {
console.log("failed")
});
}
}
}]);
angular.module('autotestApp').controller('GroupsController',
['$scope', 'GroupService', function($scope, GroupService) {
GroupService.retrieve().then(function (groups) {
$scope.items = groups;
});
}]);
One of the fixes you could use is:
for (var i = 0; i < response.length; i++) {
groups.push(response[i]);
});
That way you would have [ Object, Object, Object ]
EDIT:
One thing you could try is the following, change your retrieve function to return your promise:
return{
list: function () {
return groups;
},
retrieve: function () {
var promise = $http({
method: "get",
url: "/enterprises/_groups"
}).success(function (response) {
groups = response;
}).error(function () {
console.log("failed")
});
return promise;
}
}
and then in your controller:
angular.module('autotestApp').controller('GroupsController', function($scope, $http, GroupService) {
GroupService.retrieve().finally(function () {
$scope.items = GroupService.list();
});
});
I think your groups = response is working, but when you do $scope.items = GroupService.list() the request isn't finished yet.
do groups.concat(response)
this will flatten the items & add it to parent list rather than appending a single element.
I'm trying to make a simple login function for my AngularJS application. I'm using Dream Factory for my backend server database and I can't seem to be able to create a session from my login-function.
This is the factory I have set up:
dfdevApp.factory('SessionService', function($resource, $q) {
var sessionResource = $resource('https://dsp-myusername.cloud.dreamfactory.com/rest/user/session', {},
{ update: { method: 'PUT' }, query: {method: 'GET', isArray: false} });
return {
create: function (user) {
var deferred = $q.defer();
sessionResource.save(user, function (result) {
deferred.resolve(result);
}, function (error) {
deferred.reject(error);
});
return deferred.promise;
}
}
});
And this is the code from my controller:
// $scope.ting = Liste.get()
$scope.user = {'email' : '', 'password': ''};
$scope.login = function() {
console.log(JSON.stringify($scope.user));
$scope.user = SessionService.create(JSON.stringify($scope.user), function(success) {
$rootScope.loggedIn = true;
$location.path('/');
}, function(error) {
$scope.loginError = true;
});
};
});
I get a 400 every time I try to post.
Your post should be like this one:
{"email":"you#youremail.com","password":"yourpassword"}
Also don't forget to include your app_name in the URL or as a header (in this case, call it X-DreamFactory-Application-Name).
You can find more info here:
http://blog.dreamfactory.com/blog/bid/326379/Getting-Started-with-the-DreamFactory-API
I also built an "SDK" which handles all this for you.
https://github.com/dreamfactorysoftware/javascript-sdk