Cannot access scope variable set using Mongoose query within controller - angularjs

In my MEANJS app. I am setting the value of a scope variable to a query result, from my controller function
$scope.myVar = User.query();
console.dir($scope.myVar); //Returns all the documents from the DB correctly
console.log('User's name is : ' + $scope.myVar[0].name); //This comes as undefined
Somehow, in the very next line when I am trying to open the name field within the same controller function, it comes as undefined. Also, the entire result is being read absolutely correctly in my view file. So when I call
{{myVar.name}}
within my view file it outputs the name correctly. I cannot understand this behavior at all. This is my first time working with Angularjs, and I could have missed something basic, but I appreciate any help at this point.
Edit - Also the length of $scope.myVar is always 0 within the controller

Basically User.query() returns a promise object, so you need to update you $scope object inside promise success.
Code
User.query().$promise.then(function(res){
//you will get response here in data obj
$scope.myVar = res;
console.dir($scope.myVar);//Returns all the documents from the DB correctly
console.log('User's name is : ' + $scope.myVar[0].name); //This comes as undefined
});

EDIT: Found the answer. The callback functions in meanjs are in this format:
var myObj= User.query(function(response) {
console.log('Inside success response');
//Can access myObj values here easily
}, function(errResponse) {
console.log('Inside error response ' + errResponse);
});
I wasn't able to figure out how to access my $scope.myVar within the controller, but I completed a workaround by creating my own factory method to retrieve data the way I wanted it sorted. The problem of not being able to access these query results is really posing a problem in other parts as well. So if anyone has an answer, please do let me know.
For now posting the link I used to figure out how the MEAN.JS factory method needs to be plugged in. Hope this helps someone.
https://groups.google.com/forum/#!searchin/meanjs/query()/meanjs/4R7rIolH9bs/P1R4YlKgowUJ

Related

http.get doesn't work inside a for loop when fetching data from mongo using express

I am trying to fetch data from mongodb using express to angular inside a for loop.
I can access data inside this get instance but not outside of it. Here is my code
var daily_jobs=[];
$http.get(mongodUrl).then(function(response) {
var allMachinename = response.data;
daily_jobs=[];
for(var i = 0;i<allMachinename.length;i++){
$scope.masch_name.push({name:allMachinename[i].name,id:allMachinename[i].id,daily_jobs:[]});
$http.get(mongodUrl+'getmaschdata/'+$scope.input_id+'/'+allMachinename[i].id).then(function(jobs) {
if(jobs.data.length > 0){
daily_jobs= jobs.data;
}
console.log(daily_jobs[0].job_name);
},function(err){
console.log(err);
});
$scope.masch_name[i].daily_jobs= daily_jobs;
}
},function(err){
//console.log(err);
});
The variable daily_jobs is global, but when I want to access it outside the get function it always remain empty. How can I get that value outside of second http.get function? Any help will be appreciated. Thanks.
I couldn't get a clear picture what are you trying to achieve why are you making two http get inside a controller rather than making as a service. however to answer your question replace this
daily_jobs= jobs.data;
with
$scope.masch_name[i].daily_jobs = jobs.data;
that should work if you want to know more about this read here
Angular Share Variable betwen $http.get and controller
I will suggest you to read about services in AngularJS and $scope.apply as well for more detail

AngularJs forEach logic, not so academic but working

I've got this code working, but i don't think it is the right way to do. I think i need to use $q, but it is difficult to understand for me .
I receive correctly this nice array of json (data.data) from my angularJs factory, from my php server-mysql backend . It is some rendez-vous with a start date:
[{"id":"1","title":"Loi Travail","infos":null,
"adresse":"12 avenue des lis 78013 paris",
"criticite":"4","fichiers":null,
"start":"2017-06-11T22:37:59.012Z"},
{"id":"17","title":"jjtyjyjt","infos":"jytjjyjyj",
"adresse":"tjtyjjyj","criticite":"7","fichiers":"",
"start":"2017-06-11T22:37:59.012Z"}]
The problem is that angular-material-datetimepicker doesn't recognise the start date, because it is a string, so i need to do a loop to add new Date(), for converting each of my "start" elements.
So, i've done this short code, that is working :
rdvFactory.get_rdvs().then(function(data){
$scope.events = data.data;
angular.forEach($scope.events,function(value,index){
value.start = new Date(value.start);
})
})
It is working, meaning that i can see all of the rendez vous appearing inside angular-material-datetimepicker, but i don't think it is the right way to do, because I'm changing several time the scope(2 way binding) each iterations of angular.forEach, i suppose it is very consuming.
I think i should do a foreach on data.data for converting the dates, and after it is finished, i should set up $scope.events only after that .
I don't know if you see what i mean, but it is difficult to work with $q, i would appreciate if somebody could explain me $q a little more because even with the examples given on stackoverflow, i t is really difficult to understand the syntax.
Question : Do you think it is better to add a second .then like this ?
rdvFactory.get_rdvs().then(function(data){
$scope.events = data.data;
}).then(function(data){
angular.forEach($scope.events,function(value,index){
value.start = new Date(value.start);
})
});
In this last example, do you think the second.then really wait for $scope.events to get populated ? I'm not sure ... It is working but it is the right way to do to avoid performances problems ?
Have a nice day
Nick - you are right, changing a $scope variable is costly and would generate unnecessary digest cycles. I would suggest you do this instead -
rdvFactory.get_rdvs().then(function(data){
var tempData = data.data; // A temp local variable
angular.forEach(tempData ,function(value,index){
value.start = new Date(value.start);
}
$scope.events = tempData; // assign the final JSON to scope variable.
})
With regards to $q, its used mainly to combine two or more AJAX responses and then perform the operation. For example -
If there is an AJAX call to fetch User Details (based on ID) & another call to fetch User access rights (based on ID), then we may want to fire them together as both needs to be success for a user to login.
Incorrect flow -
Fetch User details.on success then(
//fetch user access right // on success of user details call fire user access rights.
)
Instead, you queue both the calls in an array and wait for both of them to pass or fail together.
$q = [call1, call2]
$q.then (
//on success, we know that user is correct and has right user access.
)

using data from a callback from Ebay api in Angularjs

I am trying to use the ebay api in an angular.js app.
The way the api works by itself is to pass data to a callback function and within that function create a template for display.
The problem that I am having is in adding the data returned from the callback to the $scope. I was not able to post a working example as I didnt want to expose my api key, I am hoping that the code posted in the fiddle will be enough to identify the issue.
eBayApp.controller('FindItemCtrl', function ($scope) {
globalFunc = function(root){
$scope.items = root.findItemsByKeywordsResponse[0].searchResult[0].item || [];
console.log($scope.items); //this shows the data
}
console.log($scope.items); //this is undefined
})
http://jsfiddle.net/L7fnozuo/
The reason the second instance of $scope.items is undefined, is because it is run before the callback function happens.
The chances are that $scope.items isn't updating in the view either, because Angular doesn't know that it needs to trigger a scope digest.
When you use the Angular provided async APIs ($http, $timeout etc) they have all been written in such a way that they will let Angular know when it needs to update it's views.
In this case, you have a couple of options:
Use the inbuilt $http.jsonp method.
Trigger the digest manually.
Option number 1 is the more sensible approach, but is not always possible if the request is made from someone else's library.
Here's an update to the fiddle which uses $http.jsonp. It should work (but at the moment it's resulting in an error message about your API key).
The key change here is that the request is being made from within Angular using an Angular API rather than from a script tag which Angular knows nothing about.
$http.jsonp(URL)
.success($scope.success)
.error($scope.error);
Option 2 requires you to add the following line to your JSONP callback function:
globalFunc = function(root){
$scope.items = root.findItemsByKeywordsResponse[0].searchResult[0].item || [];
console.log($scope.items); //this shows the data
$scope.$apply(); // <--
}
This method tells Angular that it needs to update it's views because data might have changed. There's a decent Sitepoint article on understanding this mechanism, if you are interested.

AngularJS $http success but not working

i'm using angularJS and SLIM PHP restful server, the PHP service is working and actually i have already used $http.get() with no problems in this application ...
But now a strange thing is happening, i created a new function in the same way that the others, and it get .success(function(data)) with no problems, i actually can console.log(data) and it shows the right results, but when .success() finish and return, i recieve a undefined result.
ps: there is no error in browser console.
var markerOptions = [];
loadMarkers();
console.log(markerOptions);
function loadMarkers() {
$http.get('http://localhost/rest/getMarkers').success(function(response){
console.log(response);
markerOptions = response;
});
}
Console.log() inside success() return the right data
Console.log() after loadMarkers() return undefined
#MarcKline's comments are correct. Anyways, following what I think you're trying to achive by this piece of code of yours, you can assign the returned data from the ajax response to a scope variable (assuming you're using $scope), e.g $scope.markerOptions = response. You can declare markOptions as a scope variable by var $scope.markOptions = [] (...and, of course, log it by console.log($scope.markOptions) accordingly). Also, define $scope.loadMarkers = function() {...} and call it by $scope.loadMarkers()
The scope will be updated as soon as the client-side gets its ajax response.
Hope it helps your current needs in addition to a better understanding of javasciprt's async approach that some of its principles were explained to you by the comments.

How to clear a model when my AngularFire app loads initially?

I am new to AngularFire and am trying to understand a simple concept. If you go through the AngularFire tutorial located at the following url: http://angularfire.com/tutorial/index.html#gettingstarted there is a rudimentary example of using AngularFire to build a primitive "chat" application.
The tutorial is very clear and concise but I do not understand one primary point with it:
function MyCtrl($scope, angularFire){
$scope.messages = [];
var ref = new Firebase("https://<xxxxxx>.firebaseio.com/messages");
angularFire(ref, $scope, 'messages');
$scope.messages = []; //shouldn't this clear the data locally and remotely?
}
The issue is that a model is first created, and then the binding magic with AngularFire is setup such that there is now a 3-way binding to the model. If there is an array of data already stored in Firebase, that data is fetched and synced and your model will now have this data locally.
What I simply do not understand is, when the controller code runs, suppose I set the model to an empty array AFTER the angularFire binding is wired up, why doesn't the Firebase data get cleared out? Never mind the fact, that refreshing the page would basically keep wiping out the data (the behavior I want).
Now, I can get this behavior to work, if I wire up an ng-click event to a button, that calls a method named clear defined on my $scope object. If within, that method, I simply call: $scope.messages = [];, then my model is cleared locally, and remotely.
But why doesn't this work on initialization?
Help is always appreciated.
I think I may have found an answer to my own problem. It looks like, you must wait until the promise returns to actually start modifying the model like so. Now whenever I refresh my page, when my .then() runs, it will clear out my data.
I suppose this is how it should be done. Can anyone confirm?
$scope.messages = [];
var ref = new Firebase("https://<xxxxxx>.firebaseio.com/items");
var prom = angularFire(ref, $scope, 'messages');
prom.then(function(){
console.log("data loaded");
$scope.messages = [];
});
I'm guessing the remote data hasn't returned yet and is populated after your second call to $scope.messages =[]
edit:
Why not just explicitly remove your data from FB before binding it to a local list.
var ref = new Firebase("https://<xxxxxx>.firebaseio.com/messages");
ref.remove();

Resources