Reputation: 8162
Following is the code that makes an http request to MyApp's API for user profile data(like name, photo) to update the navbar.
var app = angular.module('MyApp', ['ng']);
app.controller('navBarController', function($scope, $userProfile) {
$scope.userProfile = $userProfile;
console.log("$userProfile: " + JSON.stringify($userProfile));
setTimeout(function() {
console.log("$userProfile: " + JSON.stringify($userProfile));
}, 3000);
});
app.factory('$userProfile', function($http) {
var profile = null;
$http.
get('/api/v1/me').
success(function(data) {
profile = data;
console.log("profile after get: " + JSON.stringify(profile));
}).
error(function(data, $status) {
if ($status === status.UNAUTHORISED) {
profile = null;
console.log("profile if error: " + JSON.stringify(profile));
}
});
console.log("profile (finally): " + JSON.stringify(profile));
return profile;
});
app.directive('navBar', function() {
return {
controller: 'navBarController',
templateUrl: 'templates/nav_bar.html'
}
});
I am console logging to check for the unexpected results I am getting and the logs are as follows:
profile (finally): null
$userProfile: null
profile after get: {"photo":"http://localhost:3000/img/1023.jpg","name":"Utkarsh Gupta"}
$userProfile: null
The first two log msgs are obvious as $http.get()
is asynchronous so the profile is null as defined at the start of the function. But after the $http.get()
function returns successfully, the profile var got updated as shown in the third log msg but the $userProfile
service continues to be null.
Upvotes: 0
Views: 1134
Reputation: 1501
You need to first fix your services (factory). It needs to return and object. Right now you are just running async code in your service, no way for your controller to use it. Second once you fix your service (look at the code below) you need to create a function to get the user profile. The user profile function needs to return a promise since you are working with async code. Again look at the code below and I hope it helps.
var app = angular.module('MyApp', ['ng']);
app.controller('navBarController', function($scope, $userProfile) {
$userProfile.get().then(function(response){
$scope.userProfile = response;
});
setTimeout(function() {
console.log("$userProfile: " + JSON.stringify($userProfile));
}, 3000);
});
app.factory('$userProfile', function($http) {
var self = {};
self.get = getProfile;
return self;
function getProfile(){
var profile = null;
return $http.get('/api/v1/me')
.success(function(data) {
return data.data;
})
.error(function(data, $status) {
if ($status === status.UNAUTHORISED)
return profile;
});
}
});
Upvotes: 1
Reputation: 8162
Instead of initialising profile as null at the top, you must initialise it as:
var profile = {};
And then tack on to that empty profile object your API returned data like:
$http.
get('/api/v1/me').
success(function(data) {
//like this
profile.data = data;
})
In your code, when the $userProfile-service function finishes it returns the profile simply as null. And even after the $http.get request is complete your $userProfile has the same null because now the updated profile variable is not accessible anymore as it is out of scope. But if you initialize and return profile as an object, you can access it even after the function has returned because objects are passed by reference in javascript. You can then access the content of the profile object in your controller the way you are alreday doing because now $userProfile is the same exact profile object that you declared above and not a null anymore and any update on that profile object anywhere in your entire code will be reflected wherever that object is being accessed.
Upvotes: 0
Reputation: 12022
In your service, you have declared var profile = null;
and triggering the $http
api call then immediately returning the variable profile
which is null
at the time of returning and later you are updating the variable once the api got response and you are expecting it should be propagated to the controller which is not the case.
As service is
singleton
in nature, instance will be created once and never created/updated.
Hence, your code is not a recommended one to use a service. I have updated the code below where service will return a method called load
to call the api which is getting triggered from the controller where $scope
can be directly assigned with the response data.
var app = angular.module('MyApp', ['ng']);
app.controller('navBarController', function($scope, $userProfile) {
$userProfile.load().
success(function(data) {
$scope.userProfile = data;
console.log("profile after get: " + JSON.stringify($scope.userProfile));
}).
error(function(data, $status) {
if ($status === status.UNAUTHORISED) {
$scope.userProfile = null;
console.log("profile if error: " + JSON.stringify($scope.userProfile));
}
});
});
app.factory('$userProfile', function($http) {
var getProfile = function() {
return $http.
get('/api/v1/me');
};
//console.log("profile (finally): " + JSON.stringify(profile));
return {
load: getProfile
};
});
app.directive('navBar', function() {
return {
controller: 'navBarController',
templateUrl: 'templates/nav_bar.html'
}
});
Note: Also, please don't use
$
prefix to service, variable, controller names as this is reserved toAngularJS
and may create conflicts when you use the same name as AngularJS reservered keywords/services.
Upvotes: 1
Reputation: 86
Looks like your service is not injected into the controller.
Have you tried it that way?
app.controller('navBarController', ["$scope", "$userProfile", function($scope, $userProfile) {}]
Example here: https://docs.angularjs.org/guide/services
Upvotes: 1