I am trying to set the controllers scope variable to the data, however no luck. The console.log in the controller shows undefined. Appreciate the help!
My angular service has the following code --
service('VyrtEventService', ['$http', function($http) {
var events = [];
this.getArtistEvents = function(artistId) {
var url = '/api/users/' + artistId + '/';
var promise = $http.get(url).success(function(data, status, headers, config) {
events = data.artist.events;
console.log(events);
return events;
}).catch(function(error) {
status = 'Unable to load artist data: ' + error.message;
console.log(status);
});
return promise;
};
}]);
And I am referencing it in the controller as follows --
VyrtEventService.getArtistEvents($scope.artistId).then(function(data){
$scope.events = data.data.artist.events;
});
console.log($scope.events);
You should just set $scope.events = data in your controller cause your promise already returns data.artist.events when it resolves
To pass scope to service from anywhere in controller. Make sure you inject service .
controllersModule.controller('MyCtrl', function($scope, $filter, $http, $compile, ngTableParams, **FactoryYouwant**)
{
**FactoryYouwant**.getdata($scope.**scopeYoutwantTopass**).then (function(responseData){
var ResponseFromServer =responseData.data;
}
in service
controllersModule.factory('**FactoryYouwant**, function($http) {
var responseData = null;
return {
getdata : function(**data**){ (you dont have to use $)
responseData = $http.post or whatever actually gets you data;
return responseData;
}
};
});
I hope this helps you to call get data from service anywhere in controller.
Related
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.
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
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 to AngularJS and may create
conflicts when you use the same name as AngularJS reservered keywords/services.
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;
});
}
});
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.
I generate a code with editor.swagger and I want to code a GUI with angular for that code. Since I'm newbie in angular, I dind't understand well how to start programming. I first decide to create 3 files : index.html, index.js and service.js.
Here is a part of my code :
I don't know if it's the good beginning or not. But the problem is that I don't have any idea how what I should do for POST and DELETE. Can you help me please?
You can do the standard 4 methods in Angluar JS(POST,GET,PUT,DELETE). To use these in angular you have to use the $http service that angular provides. To find out more about it check their documentation: https://docs.angularjs.org/api/ng/service/$http
From the Angular $http documentation:
Complete list of shortcut methods:
$http.get
$http.head
$http.post
$http.put
$http.delete
$http.jsonp
$http.patch
You can also use the method parameter in the $http service. So $http(method: 'DELETE', ...)
var app = angular.module('app');
app.service('apiService', ['$http', function($http){
this.get = function(){
return $http.get(URL);
};
this.delete = function(id){
return $http.delete(URL, id);
}
this.post = function(data){
return $http.post(URL, data);
}
}]);
app.controller('controller', ['$scope', 'apiService', function($scope, apiService){
var getData = apiService.get().success(function(){
});
}]);
You can use $resource and return it as a service.
app.factory('factoryResource', ['$resource', function($resource) {
var resource = {
getResource: function(context) {
var rsc = $resource(context, {}, {'update': {method: 'PUT'}});
return rsc;
}
};
return resource; }])
In your controller you should inject the newly created service as below:
app.controller('myCtrl', function($scope, factoryResource) {
$scope.resource = factoryResource.getResource('http://localhost:8080/api/v1/projects');
$scope.resource.save(object, successCallback, errorCallback); //post
$scope.resource.query(successCallback, errorCallback); //get all
$scope.resource.get({id: object.id}, successCallback, errorCallback); //get a specific object
$scope.resource.delete({id: object.id}, successCallback, errorCallback); //delete
}
Hope this helps;
Basically we have 4 method for a REST operation
Create (POST)-- To Create a new User (just for an example, it can be anything)
Read (GET) -- To get all users
Update (PUT) -- To update a user's property
Delete (DELETE) -- To delete a user
Let me know if you need further clarification.
In angular using service you can do that.
var app = angular.module('app', []);
app.factory('UserService', function($http){
var user = {};
user.post = function(data){
return $http.post('url', data);
}
user.get = function(){
return $http.get('url');
}
user.delete = function(id){
return $http.delete('url');
}
user.update = function(id, data){
return $http.put('url', data);
}
return user
});
app.controller('Controller', function('UserService'){
// Get
UserService.get().success(function(){
});
UserService.post(data).success(function(){
});
UserService.delete(id).success(function(){
});
UserService.get(id, data).success(function(){
});
})
This can be done easily through $resource, if you URL is proper rest.
I'm trying to add a service to my Angular project for the first time and running into issues injecting it within my controller.
I am getting an error of --
TypeError: Cannot read property 'get' of undefined
I'm looking to properly inject the service into the controller and ways I can improve the code for best practices/efficiency.
Thanks for the help!
I have a folder /event in my angular project with the following files --
app.js
controllers.js
directives.js
services.js
app.js file has --
'use strict';
angular.module('vyrt.event', [
'vyrt.event.controllers',
'vyrt.event.services',
'vyrt.event.directives'
]);
services.js file has --
'use strict';
angular.module('vyrt.event.services', []).
service('VyrtEventService', ['$http', function($http) {
var artistId = 0,
artist = '',
events = [],
active_event_idx = 0;
this.get = function(artistId) {
var url = '/api/users/' + artistId + '/';
$http.get(url).success(function(data, status, headers, config) {
artist = data.artist.user;
events = data.artist.events;
active_event_id = data.artist.events[0].id;
});
return artist, events, active_event_id;
}
}]);
finally, the controller has --
'use strict';
angular.module('vyrt.event.controllers', []).
controller('VyrtEventCtrl', ['$scope', function($scope, VyrtEventService) {
console.log(VyrtEventService.get($scope.artistId));
$scope.activeCampaign = function(idx) {
if (idx == VyrtEventService.active_event_idx) return true;
return false;
};
}]);
The problem is that you've forgotten to put 'VyrtEventService' in your dependency list when you define you controller:
.controller('VyrtEventCtrl', ['$scope', /* you need this ==>*/ 'VyrtEventService', function($scope, VyrtEventService) {
console.log('VyrtEventService', VyrtEventService);
$scope.activeCampaign = function(idx) {
if (idx == VyrtEventService.active_event_idx) return true;
return false;
};
}]);
Update
Your get() function has a couple of issues. First, you need to return the $http.get() call itself and then you can call then() in your controller and set the results to a property on your $scope there. Second, you can't return multiple values like that. You would have to return an array of values or an object with your desired values assigned to it.
service
this.get = function(artistId) {
var url = '/api/users/' + artistId + '/';
return $http
.get(url)
.catch(function(error){
// handle errors here
console.log('Error fething artist data: ', error);
});
}
controller
VyrtEventService
.get(artistId)
.then(function(data){
$scope.artist = data.artist.user;
$scope.events = data.artist.events;
$scope.active_event_id = data.artist.events[0].id;
});
$scope.activeCampaign = function(idx) {
return (idx == $scope.active_event_idx);
};
I am working using Angular JS. I am trying to get a json object obtained using $http service to be accessible in a $scope variable. Inside all the asynchronous AJAX ($http.get()) calls, if I try to print the data obtained stored inside a $scope variable and print it, it works successfully and shows me the expected data. But outside scope of the asynchronous method, the same $scope variable assigned with data obtained loses hold of it and prints undefined.
Code:
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
return {
list: function(){
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
});
return deferred.promise;
}
};
}
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$http', 'getTestcaseFactory', function($scope, $routeParams, $http, getTestcaseFactory) {
$scope.myjsonobj = '';
var fetchTestcaseDetails = function() {
getTestcaseFactory.list()
.then(
function(data) {
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
},
function(data) {
alert(data);
});
}
fetchTestcaseDetails();
console.log($scope.model); //Prints undefined
}]);
By the time
console.log($scope.model);
executes, the $http request would have not gone through yet, and this is why it prints undefined. Once the $http request is done, your $scope.model will update accordingly. You can test this by using a $timeout
$timeout(function () {
console.log($scope.model);
}, 5000);
Don't forget to inject $timeout in your controller.
This saves my day! $timeout to the rescue. Thanks #Dan Moldovan for the answer! As the $http service is asynchronous, we have to set a timer to wait for a time interval till the point the data is really received in the promise.success section and then it can be assigned to a variable inside $scope.
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q) {
return {
list: function(){
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
});
return deferred.promise;
}
};
}
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$timeout', 'getTestcaseFactory', function($scope, $routeParams, $timeout, getTestcaseFactory) {
var fetchTestcaseDetails = function() {
getTestcaseFactory.list()
.then(
function(data) {
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
},
function(data) {
alert(data);
});
}
fetchTestcaseDetails();
$timeout(function() {
console.log($scope.model); //Prints the Data now
}, 2000);
}]);
The solutions posted so far are fundemantally wrong, as they depend on an arbitrary timeout, and nothing guarantees that the async answer will be available by then.
As I suggested in a comment above, here are 2 more data/event-driven solutions.
You either only print in the callback function (which you're already doing in your example)
Or since you're using angular anyway, you can set up a watch (which in the background uses a not-too-nice dirty checking solution, but at least it's abstracted away from your code)
If you want to run a function called processData once the data is available, solution 1 you already do in your example, see this line:
console.log($scope.model);//PRINTS THE RIGHT DATA
Here you could call any other function to trigger the continuation of the process, just call whatever function:
console.log($scope.model);//PRINTS THE RIGHT DATA
processData();
Using angular's $watch mechanism (2.):
$scope.$watch(
function(){return $scope.model;},
function(newValue, oldValue){
if(newValue != null){
console.log($scope.model);
processData();
}
})
This will print the data when it is available after the async callback, and the program will continue with processing from then.
I am new in AngularJS. I was trying to call json file from factory function but it's showing my var customers = []; array is not updating. Please help.
Below is my code.
var demoApp = angular.module("myApp", []);
demoApp.factory('simpleFactory', ['$http', function($http){
return {
getCustomer: function(){
var customers = [];
return $http.get("http://www.w3schools.com/website/Customers_JSON.php")
.success(
function(data){
customers = data;
},
function(error){
console.log(error);
});
console.log(customers)
}
}
}]);
demoApp.controller("emplyCtrl", function($scope, simpleFactory){
$scope.customers = simpleFactory.getCustomer();
});
Demo Fiddle
Try something like this:
demoApp.factory('simpleFactory', ['$http', function($http){
return {
getCustomer: function(){
return $http.get("json/customers.json").then(
function(response){
var customers = [];
customers = response.data;
},
function(error){
console.log(error);
});
}
}
}]);
use this in your controller:
demoApp.controller("emplyCtrl", function($scope, simpleFactory){
simpleFactory.getCustomer().then(function(response){
$scope.customers = response.data;
});
});
Since the view (HTML) reads from the controller's $scope, you have to put the data in $scope somewhere in the controller. Setting it in the factory only allows access from within the factory.
Here is the working Fiddle
Hope this helps!
Don't you think that you should put "$" sign before http?
I think that the '$http' there should indicate that it is serializable. That is why, the $http should be stated in the parameter section the same way just like you mentioned in the previous string statement.
Additionally, you cannot just use http, since the syntax is to use $ in front of the http.
Otherwise, angular dll will not recognize your code.
demoApp.factory('simpleFactory', ['$http', function($http){
var customers = [];
$http.get("json/customers.json")
.success(function(data){
customers = data;
});
var factory = {};
factory.getCustomer = function(){
return customers;
};
return factory;
}]);
Take a look at the example here:
http://www.w3schools.com/angular/angular_http.asp
Thank you,