How return `$resource` promise response? - angularjs

I require the user details for multiple areas. I tried to return the details using a generic function. But i am getting the result as undefined. i understand that, I require to use the $differed to get the reuslt. But I don't have any idea about my current scenario.
anyone help me here please?
here is my function:
$scope.currentUserInfo = function () {
var userDetails;
server.getProfile.get().$promise.then(function ( response ) {
if( response.Message.toUpperCase().indexOf('SUCCESS') != -1) {
return userDetails = response;
}
return "Not able to get the user details this time"
})
return userDetails;
}
$scope.currentUser = $scope.currentUserInfo();
console.log( $scope.currentUser ) //undefined.
var function1 = function () {
$scope.currentUserInfo(); //once user details available do further
$scope.age = $scope.currentUser.age;
}
var function2 = function () {
$scope.currentUserInfo(); //once user details available do further
$scope.name = $scope.currentUser.name;
}

server.getProfile.get() is an asynchronous call.
The return userDetails; line in $scope.currentUserInfo function will get executed even if the server.getProfile.get() call is not yet finish.
Try this:
$scope.currentUserInfo = function () {
server.getProfile.get().$promise.then(function ( response ) {
if( response.Message.toUpperCase().indexOf('SUCCESS') != -1) {
$scope.currentUser = response;
}
$scope.message = "Not able to get the user details this time";
})
}
$scope.currentUser will be populated after the ajax call is finish. I assume that you are using $scope.currentUser in your html bindings so when the value changes it will automatically reflect in your view

Related

AngularJS: Passing Promise, yet Cannot read property 'finally' of undefined

In my angular app, I have 2 methods save() and saveTriggers(). saveTriggers() updates all records by calling a web service (C#). I want to make sure that a block of code is executed after all records are updated in saveTriggers() and control is returned to save(). I believe I need to pass something from the saveTriggers() to make finally block execute. I tried various things, nothing works. Using .then() also gives the same error. I am not that good at JS. Can you please guide me.
vm.updatedTriggers = []; // IDs are pushed in
vm.saveTriggers = function () {
if (vm.updatedTriggers.length === 0) {
vm.close();
} else {
vm.saving = true;
vm.save()
.finally(function () { // ERROR - Cannot read property 'finally' of undefined
console.log("Saved all. Closing..."); // Never REACHES here
vm.saving = false;
vm.updated = true;
$uibModalInstance.close(true);
});
}
};
vm.save = function () {
//vm.saving = true;
for (var i = 0; i < vm.updatedTriggers.length; i++) {
var trigger = vm.triggers.find(t => t.id === vm.updatedTriggers[i]);
var input = {
id: trigger.id,
target: trigger.target,
targetInfo: vm.targetData,
event: trigger.event,
eventQuantity: trigger.eventQuantity,
eventQuantityExtra: trigger.eventQuantityExtra
};
rpmService.editDeviceTrigger(input);
/*.finally(function () {
console.log("Updated event"); // Reaches here
vm.updated = true;
return Promise.resolve(2);
});*/ // Commenting this also doesn't help
}
return Promise.resolve(2);
};
rpmService.editDeviceTrigger(input)
public async Task EditDeviceTrigger(EditDeviceTriggerInput input) {
// calls other methods with await
// Doesn't return anything
}
EDIT: Updated Code: I got rid of the error, but the output is not is expected series.
vm.saveTriggers = function () {
vm.saving = true;
vm.save().then
(function success() {
console.log("Returned Result ");
console.log("Saved all. Closing..."); // These lines are executed before the event is upated
vm.saving = false;
$uibModalInstance.close(true);
});
};
vm.save = function () {
var deferred = $q.defer();
for (var i = 0; i < vm.updatedTriggers.length; i++) {
var trigger = vm.triggers.find(t => t.id === vm.updatedTriggers[i]);
var input = {
id: trigger.id,
....
};
rpmService.editDeviceTrigger(input)
.finally(function () {
console.log("Updated event"); // Successfully updates all events
vm.updated = true;
});
}
deferred.resolve();
return deferred.promise;
};
OUTPUT:
Returned Result
Saved all. Closing...
Updated event
EXPECTED OUTPUT:
Updated event
Returned Result
Saved all. Closing...
Thanks.
Usually you dont need $q.defer-related things, but u can do same using it if u want.
Here I guess you just need to collect all your save promises and return new resulting one using $q.all:
vm.save = function () {
const myAwesomePromises = []
for (var i = 0; i < vm.updatedTriggers.length; i++) {
...
const savePromise = rpmService.editDeviceTrigger(input);
savePromise.finally(() => console.log('edit device finally'));// <-- not sure u need this
myAwesomePromises.push(savePromise);
}
return $q.all(myAwesomePromises).finally(() => console.log('All edit device finally'));
};

How to return response to calling function in AngularJS?

I am calling this method testDataService, which is defined in the same JS file. This method returns a list which it gets from an API call. I want to set that value to model and return model object. but my return function is getting called before my API returns the response. How can i make sure return function will get called only after the above if block get the data from API.
getTestData(model) {
model.name = "practice";
model.value = 2;
// this if loop is calling an API and setting up data into model.
if(this.model.form.length>0 && this.model.form[0].entityName === 'test'){
let responseList;
this.testDataService(this.model).then(response => {
responseList = response;
model.class = responseList;
});
}
return this.model;
// this return function is getting called before the api returns its data. How can i make sure this return will get called only after the above if block get the data from API.
}
This is method definition
testDataService(model) {
let profileType = "test";
let profileId = "test_profile";
let configCategory = "test";
return this.referenceDataService.getTestData(profileType, profileId, configCategory);
}
You need to pass return statement from the callback, instead of placing it outside.
getTestData(model) {
model.name = "practice";
model.value = 2;
// this if loop is calling an API and setting up data into model.
if (this.model.form.length > 0 && this.model.form[0].entityName === 'test') {
this.testDataService(this.model).then(response => {
let responseList = response;
model.class = responseList;
return this.model;
}).then(response => {
return null;
});
}
}
testDataService(model) {
let profileType = "test";
let profileId = "test_profile";
let configCategory = "test";
return this.referenceDataService.getTestData(profileType, profileId, configCategory);
}

Angular template won't load. Even with $loaded. Data resolves after Load

Using AngularFire, Angular, Firebase.
I load a list of users from a Firebase Database. I use $loaded to ensure it waits until data loads.
I take this list, compare it against another firebase database of groups and push the results into two arrays.
Based on the console.logs the data sorts correctly. However, inside my template I get a blank page (I think this is because the page loads before the data is sorted).
Thoughts?
let userLoggedIn = AuthFactory.getUser();
var allUsersArray = $firebaseArray(ConnectFactory.fbUserDb);
var x = firebase.database().ref('groups');
var friendArr = [];
var notFriendArr = [];
allUsersArray.$loaded().then(function(){
angular.forEach(allUsersArray, function(user, i) {
var haveIAdded = x.child(userLoggedIn).child(allUsersArray[i].uid).once('value').then(function (snap) {
if (snap.val() !== null) {
return true;
} else {
return false;
}
});
var haveTheyAdded = x.child(allUsersArray[i].uid).child(userLoggedIn).once('value').then(function (snap) {
if (snap.val() !== null) {
return true;
} else {
return false;
}
});
Promise.all([haveIAdded, haveTheyAdded]).then(function([you, they]) {
if (you && they) {
console.log('We Are Friends', allUsersArray[i]);
friendArr.push(allUsersArray[i]);
} else {
console.log('not a friend ', allUsersArray[i]);
notFriendArr.push(allUsersArray[i]);
}
});
});
$scope.friendList = friendArr;
$scope.notFriendList = notFriendArr;
});
Alright, this time I tried to actually read the question before attempting to answer. ;-)
When you set your $scope.friendList and $scope.notFriendList within the $loaded promise, your Promise.all may (and most likely) havn't resolved yet when those are called, since angular.forEach doesn't wait for the promises to finish before moving on to the next statement in the function. So you'll have to build an array of promises and wait for them all to resolve outside of the loop before attempting to set your $scope variables.
allUsersArray.$loaded().then(function(){
var promises = [];
var friendArr = [];
var notFriendArr = [];
angular.forEach(allUsersArray, function(user, i) {
... // Same as before
promises.push(
Promise.all([haveIAdded, haveTheyAdded]).then(function([you, they]) {
if (you && they) {
console.log('We Are Friends', allUsersArray[i]);
friendArr.push(allUsersArray[i]);
} else {
console.log('not a friend ', allUsersArray[i]);
notFriendArr.push(allUsersArray[i]);
}
})
);
});
Promise.all(promises).then(function(){
$scope.friendList = friendArr;
$scope.notFriendList = notFriendArr;
});
});

Firebase .once(): Use success and failure callbacks

I have the following function in my Angular-app
$scope.retrieveProjectData = function() {
$scope.projectNumberNoChange = false;
// Only retrieve Data if the ProjectNumber changed
if (currentlySelectedProjectNumber != $scope.feedback.projectNumber.content) {
currentlySelectedProjectNumber = $scope.feedback.projectNumber.content;
// Go to database-reference based on the projectNumber
var projectsRef = firebaseDatabaseRef.child("projects");
var currentChild = projectsRef.child(currentlySelectedProjectNumber);
// retrieve data once and fill $scope.feedback
currentChild.once("value",
// If the project is found
function (dataSnapshot) {
// Fill selectedProject and hand over to writeDataFromSelectedProject()
var selectedProject = dataSnapshot.val();
// Fill $scope.feedback
writeDataFromSelectedProject(selectedProject);
},
// If no data is found
function () {
console.log("No data found");
});
}
// If the projectNumber didn't change, the projectNumberNoChangeMessage will be shown
else {
$scope.projectNumberNoChange = true;
}
};
The user has the possibility to load some data regarding his project-number (for instance: Name, email, tel) to make it faster for the user to fill a form.
In the part:
currentChild.once("value",
// If the project is found
function (dataSnapshot) {
// Fill selectedProject and hand over to writeDataFromSelectedProject()
var selectedProject = dataSnapshot.val();
// Fill $scope.feedback
writeDataFromSelectedProject(selectedProject);
},
// If no data is found
function () {
console.log("No data found");
});
only the first Callback-function is called, even if the projectNumber was not found. How can I use the "failureCallbackOrContext" as described in the docs?
Thanks for taking the time!
The problem was solved. I just checked the dataSnapshot.val() for beeing an object or null!

binding to service variable, doesnt refresh (service changes the var frequently)

In my Service i have the vars i want to display and the getters for it:
var docsLoaded = 0;
var docsToLoad = null;
pouchService.getDocsLoaded = function () {
return docsLoaded;
};
pouchService.getDocsToLoad = function () {
return docsToLoad;
};
While the service is syncing, i want to count the synced docs
pouchService.syncNow = function () {
var foundLastSeq = false;
docsLoaded = 0;
docsToLoad = null;
remoteDB.info().then(function (remoteInfo) {
function findOutDiff(localPosition) {
docsToLoad = (remoteInfo.update_seq - localPosition) + 1;
console.log("docs to load: " + docsToLoad);
}
// start Sync progress
sync = localDB.sync(remoteDB, {live: false})
.on('change', function (info) {
console.log('AI change: ');
console.log(info);
if (info.direction === 'pull') {
if (foundLastSeq === false) {
foundLastSeq = true;
findOutDiff(info.change.last_seq);
}
}
console.log(docsLoaded + " from " + docsToLoad);
docsLoaded++;
})
In my HTML i want to display the progress like this:
{{pouchService.getDocsLoaded()}} from {{pouchService.getDocsToLoad()}}
Now i get sometimes a value from getDocsLoaded, but mostly its zero. When I cancel the Syncprogress i get the value where it's stopped.
So i get the value before it really starts and when it's over, but i want it during the sync progress. (on the console my my progressinfos are working as expected)
Any ideas?
The problem is in applying scope. Jim wrote a nice article about this problem:
jimhoskins.com/2012/12/17/angularjs-and-apply.html
Solved it:
$rootScope.$apply(function () {
docsLoaded++;
});

Resources