This question already has answers here:
AngularJs ReferenceError: $http is not defined
(3 answers)
Closed 4 years ago.
I keep getting the following error:
Cannot read property 'get' of undefined
at Object.getChannelIdFromYoutubeUsername
at Object.vm.creatorAccountCreationFormSubmit
Even though I am injecting $http into my service, and whenever I paste the url being passed into the $http.get command, I get an output in my browser window.
Here is my service:
angular.module('adsomaApp').service('YoutubeService', function($log) {
var url = 'https://www.googleapis.com/youtube/v3';
function getChannelIdFromYoutubeUsername(youtubeApi, youtubeUsername, $http) {
var queryUrl = url + "/channels/?key=" + youtubeApi + "&forUsername=" + youtubeUsername + "&part=id";
return ($http.get(queryUrl).then(handleSuccess, handleError));
}
function handleSuccess(response) {
return response.data;
}
function handleError(response) {
if (!angular.isObject(response.data) || !response.data.message) {
return ($q.reject('An unknown error occurred.'));
}
return ($q.reject(response.data.message));
}
var youtubeService = {
getChannelIdFromYoutubeUsername: getChannelIdFromYoutubeUsername
};
return youtubeService;
});
Here is my controller:
vm.channelId = {};
vm.creatorAccountCreationFormSubmit = function() {
YoutubeService.getChannelIdFromYoutubeUsername(ConstantsService.youtubeSettings().youtubeApiKey, vm.connectYoutubeFormData.youtubeUsername).then(function(succ) {
vm.channelId = succ;
$log.info(vm.channelId);
}, function error(err) {
$log.error('Error: ', err);
});
};
angular.module('adsomaApp').service('YoutubeService', function($log, $http) { }
you didn't inject in service layer so it is showing undefin
Two basic changes:
Inject $http into the Service
angular.module('adsomaApp').service('YoutubeService', function($http, $log) {
Remove $http from the arguments of this service method
function getChannelIdFromYoutubeUsername(youtubeApi, youtubeUsername) {
The issue is that, when this Service Method is being called from the Controller, the third argument is NOT sent by you. Which, basically means, $http will be null.
I have addressed this issue by injecting $http in the service and by excluding the third argument in the method signature.
These two changes should take care of the issue. I have not included rest of the code.
Related
I am trying to give access to a json file that contains config information for my project (things like rev number, project name, primary contact, etc) I created a factory that retrieves the json file using http.get, I can then pull that data into my controller but I am unable to access it from anywhere in the controller.
I did not write the factory, I found it as an answer to another person's question and it is copied almost entirely so if it not the right way to accomplish what I am trying to do please correct me.
here is the factory:
app.factory('configFactory', ["$http", function($http) {
var configFactory = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('assets/json/config.json').then(function(response) {
// The then function here is an opportunity to modify the response
console.log(response.data.config);
// The return value gets picked up by the then in the controller.
return response.data.config;
});
// Return the promise to the controller
return promise;
}
};
return configFactory;
}]);
and here is my controller:
app.controller('footerController', ['$scope', '$rootScope', 'configFactory', function footerController($scope, $rootScope, configFactory) {
var body = angular.element(window.document.body);
$scope.onChange = function(state) {
body.toggleClass('light');
};
configFactory.async().then(function(d) {
$scope.data = d;
// this console log prints out the data that I am trying to access
console.log($scope.data);
});
// this one prints out undefined
console.log($scope.data);
}]);
So essentially I have access to the data within the function used to retrieve it but not outside of that. I can solve this with rootScope but I am trying to avoid that because I think its a bandaid and not a proper solution.
Any help would be great but this is my first experience with http.get and promises and all that stuff so a detailed explanation would be very much appreciated.
[EDIT 1] The variables from the config file will need to be manipulated within the web app, so I can't use constants.
Don't assign your response data to scope variable , create a property in your factory itself and assign the response to this property in your controller when your promise gets resolved.This way you will get the value in all the other controllers.
I have updated your factory and controller like below
app.factory('configFactory', ["$http", function($http) {
var configFactory = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('assets/json/config.json').then(function(response) {
// The then function here is an opportunity to modify the response
console.log(response.data.config);
// The return value gets picked up by the then in the controller.
return response.data.config;
});
// Return the promise to the controller
return promise;
},
config:'' // new proprety added
};
return configFactory;
}]);
app.controller('footerController', ['$scope', '$rootScope', 'configFactory', function footerController($scope, $rootScope, configFactory) {
var body = angular.element(window.document.body);
$scope.onChange = function(state) {
body.toggleClass('light');
};
configFactory.async().then(function(d) {
// $scope.data = d;
configFactory.config=d;
// this console log prints out the data that I am trying to access
console.log($scope.data);
});
// this one prints out undefined
console.log($scope.data);
}]);
Have you looked into using angular constants? http://ilikekillnerds.com/2014/11/constants-values-global-variables-in-angularjs-the-right-way/ You can leverage them as global variables accessible from any controller without the ramifications of assigning the values to rootScope
I am using 2 service in controller
First Service is to get AjaxResponse where logic to fetching the response is mentioned
The second Service calls the first service to make Http request and get result and then, in turn, return it to the controller
Ctrl Dependency injected firstService,secondService
this.getService = secondService.getData(param);
First Service--> firstService
this.httpResponse(param){
var re = $http.get(param);
return re.then(success,fail);
}
function success(data){
return data;
}
function fail(data){
console.log(data);
}
Second Service (Dependency injection of First Service)
function secondService(firstService){
this.getData = function(param){
return firstService.httpResponse(param);
};
}
this.getService is coming as undefined, all the call are going properly.
Even tried the following code:
secondService.getData(param).then(function(data){console.log(data);});
That doesn't help either.
You should chain the promises in these kinds of situations.
First, you define your service. It should contain two distinct functions. As an example, I did a GET and a POST.
angular.module("myApp",[]).factory("SharedServices", function($http) {
return {
getItem: function() {
return $http.get('path/to/api');
},
postItem: function(payload) {
return $http.post('path/to/api', payload);
}
};
});
Then, reference the service in your controller. getItem() will return a promise, where you can use it using .then to call your second service in the success callback.
angular.module("myApp",[]).controller("MainCtrl", function($scope, SharedServices) {
SharedServices.getItem().then(function(response) {
//success, got something
//call the second part
var payload = { myPayload: response.data.someItem };
SharedServices.postItem(payload).then(function(response) {
//success
}, function(response) {
//an error has occurred to the second call--POST
});
}, function(response) {
//an error occurred to the first call--GET
});
});
Used Callback to get the result.It is similar to deferred(promise)
How to access the controller method inside factory.
//controller.js
$rootScope.stackTraceReport = function(error){
var exception = errorHandler(error);
//reproting to server
StackTrace.report(exception,serviceUrl);
}
// factory.js
.factory('viewPdfFailure',['scrollTop', '$timeout', function(scrollTop, $timeout) {
return {
viewError: function ($scope, $rootScope, data, status, headers, config, accessForbiddenMessage, genericErrorMessage) {
$timeout(function () {
$scope.errorMessages = [];
$scope.infoMessages = [];
}, 7000);
console.error('Error in viewDocument, status: ' + status);
if (status == 403) {
$scope.errorMessages.push(accessForbiddenMessage);
scrollTop.onErrorScrollTop('id-header');
} else {
$scope.errorMessages.push(genericErrorMessage);
scrollTop.onErrorScrollTop('id-header');
}
$rootScope.stackTraceReport(data);
}
Help me figure out how can I access this controller method inside the factory. I am getting the method not defined error. Do I need to inject the controller inside the factory?
I think you are facing this error because when you call the $rootScope.stackTraceReport(data); method you dont defined it (calling the $rootScope.stackTraceReport = function(error){...}).
Make sure the function definition is called first (you can put two console.log to see witch is called first.
But I think its better you create a singleton Util factory to make all this "globals" functions is the same file and make sure the function is defined when you call it. (http://blog.jdriven.com/2013/03/how-to-create-singleton-angularjs-services-in-4-different-ways/)
The method should be defined in the run method so as to consume it elsewhere:
Code:
.run(['$rootScope', 'StackTrace', function ($rootScope, StackTrace) {
$rootScope.stackTraceReport = function (error) {
var exception = errorHandler(error);
//reproting to server
StackTrace.report(exception, serviceUrl);
}
}]);
I am following https://github.com/StarterSquad/startersquad.github.com/tree/master/examples/angularjs-requirejs-2 folder structure in my app
inside services i have added following code
define(['./module'], function(services) {
'use strict';
services.factory('CreditCard', ['$http', function($http) {
function CreditCardFactory() {
function parseMessage(message) {
if (message.response) {
return message.response;
}
}
function CreditCard(value) {
angular.copy(value || {}, this);
}
CreditCard.$get = function(id) {
var value = this instanceof CreditCard ? this : new CreditCard();
$http({
method: 'GET',
url: '/creditcards/' + id
}).then(function(response) {
var data = response.data;
if (data) {
angular.copy(parseMessage(data), value);
}
});
return value;
};
CreditCard.prototype.$get = function(id) {
CreditCard.$get.call(this, id);
};
return CreditCard;
}
return CreditCardFactory;
}]);
});
i have followed this question and added above code in factory
Angularjs - customizing $resource
in this question
app.controller('CreditCardCtrl', function($scope, CreditCard) {
$scope.creditCard = CreditCard().get(3);
});
CreditCard is added without adding dependency as we add defualt angular services like $scope and $http.
if i dont add dependency
controllers.controller('myListCtrl', ['Phone','Phone1','loginForm','$scope','$http','user_resources',function(Phone,Phone1,loginForm,$scope,$http,user_resources,CreditCard){
then it gives undefined and if i add it in my controller as dependency and then try to call get function then response is not returned
controllers.controller('myListCtrl', ['Phone','Phone1','loginForm','$scope','$http','CreditCard',function(Phone,Phone1,loginForm,userSrv,$scope,$http,user_resources,CreditCard){
'CreditCard' isn't declared as a dependency in this example, therefore it is not being injected and is undefined...
controllers.controller('myListCtrl', ['Phone','Phone1','loginForm','$scope','$http','user_resources',
function(Phone,Phone1,loginForm,$scope,$http,user_resources,CreditCard){
To fix this, add 'CreditCard'...
controllers.controller('myListCtrl', ['Phone','Phone1','loginForm','$scope','$http','user_resources','CreditCard',
function(Phone,Phone1,loginForm,$scope,$http,user_resources,CreditCard){
In the second example, some dependencies are missing, causing the others to be in the wrong order in comparison to the function arguments...
controllers.controller('myListCtrl', ['Phone','Phone1','loginForm','$scope','$http','CreditCard',
function(Phone,Phone1,loginForm,userSrv,$scope,$http,user_resources,CreditCard){
Add the missing dependencies in the right order...
controllers.controller('myListCtrl', ['Phone','Phone1','loginForm','userSrv','$scope','$http','user_resources','CreditCard',
function(Phone,Phone1,loginForm,userSrv,$scope,$http,user_resources,CreditCard){
I have a factory that returns an object from $http.get
app.factory( 'myFactory', function($http) {
return {
get: function() {
return $http.get('/data').success(function(data) {
return data
})
}
}
})
then
$scope.listings = myFactory.get()
In index.html, I use ng-repeat on listings.data and there is no problem finding each object.
Then from a directive I call .getListings() that's in my controller and in the Chrome Javascript console $scope.listings =
Object {then: function, success: function, error: function, $$v: Object}
Why can't I just use this?
$scope.listings.data
And is it ok to use this?
$scope.listings.$$v.data
What is $$v?
You are making little mistake in your code with get in service you return a promise object which will be filled when you sucessfully complete response from the server so kindly modify your code below to make it working.
app.factory( 'myFactory', function($http) {
return {
get: function() {
return $http.get('/data')
}
}
})
myFactory.get().then(function(data){
$scope.listings=data;
});