I'm trying to run a function inside .factory to get posts, but I get an undefined error on my controller.
.factory('Portfolio', function($http, $log) {
//get jsonp
this.getPosts = function($scope) {
$http.jsonp("http://test.uxco.co/json-test.php?callback=JSON_CALLBACK")
.success(function(result) {
$scope.posts = $scope.posts.concat(result);
$scope.$broadcast("scroll.infiniteScrollComplete");
});
};
});
.controller('PortfolioCtrl', function($scope, Portfolio) {
$scope.posts = [];
Portfolio.getPosts($scope);
Thanks!
What you wrote is a service not a factory. so you either
change it to be .service instead of .factory.
or return the function inside an object like this
.factory('Portfolio', function($http, $log) {
//get jsonp
return {
getPosts: function($scope) {
$http.jsonp()
.success(function(result) {
$scope.posts = $scope.posts.concat(result);
$scope.$broadcast("scroll.infiniteScrollComplete");
});
};
}
});
check the difference between service and factory
Use .factory code like this
.factory('Portfolio', function($http, $log) {
//get jsonp
return{
getPosts: function($scope) {
$http.jsonp("http://test.uxco.co/json-test.php?callback=JSON_CALLBACK")
.success(function(result) {
$scope.posts = $scope.posts.concat(result);
$scope.$broadcast("scroll.infiniteScrollComplete");
});
};
}
});
Related
I am trying to create a service to get json and pass it to me homeCtrl I can get the data but when a pass it to my homeCtrl it always returns undefined. Im stuck.
My Service:
var myService = angular.module("xo").factory("myService", ['$http', function($http){
return{
getResponders: (function(response){
$http.get('myUrl').then(function(response){
console.log("coming from servicejs", response.data);
});
})()
};
return myService;
}
]);
My Home Controller:
var homeCtrl = angular.module("xo").controller("homeCtrl", ["$rootScope", "$scope", "$http", "myService",
function ($rootScope, $scope, $http, myService) {
$scope.goData = function(){
$scope.gotData = myService.getResponders;
};
console.log("my service is running", $scope.goData, myService);
}]);
You should return promise from getResponders function, & when it gets resolved it should return response.data from that function.
Factory
var myService = angular.module("xo").factory("myService", ['$http', function($http) {
return {
getResponders: function() {
return $http.get('myUrl')
.then(function(response) {
console.log("coming from servicejs", response.data);
//return data when promise resolved
//that would help you to continue promise chain.
return response.data;
});
}
};
}]);
Also inside your controller you should call the factory function and use .then function to get call it when the getResponders service function resolves the $http.get call and assign the data to $scope.gotData
Code
$scope.goData = function(){
myService.getResponders.then(function(data){
$scope.gotData = data;
});
};
This is an example how I did for my project, it work fine for me
var biblionum = angular.module('biblioApp', []);//your app
biblionum.service('CategorieService', function($http) {
this.getAll = function() {
return $http({
method: 'GET',
url: 'ouvrage?action=getcategorie',
// pass in data as strings
headers: {'Content-Type': 'application/x-www-form-urlencoded'} // set the headers so angular passing info as form data (not request payload)
})
.then(function(data) {
return data;
})
}
});
biblionum.controller('libraryController', function($scope,CategorieService) {
var cat = CategorieService.getAll();
cat.then(function(data) {
$scope.categories = data.data;//don't forget "this" in the service
})
});
I would like to store the value from /api/login.json globally using a service, but I think I have some sort of timing issue. The console.log statement in the controller tells me that the scope.login object is undefined.
What am I missing?
Thanks!
Factory service:
myApp.factory('LoginFactory', ['$http', function($http){
this.data;
$http.get('/api/login.json').success(function(data) {
this.data = data;
});
return {
getData : function(){
return this.data;
}
}
}]);
Controller:
myApp.controller('AccountsCtrl', ['$scope', 'Accounts', 'LoginFactory', function($scope, Accounts, LoginFactory){
$scope.login = LoginFactory.getData();
console.log('$scope.login: %o', $scope.login);
$scope.accounts = Accounts.index();
}]);
you should probably avoid use of the this keyword in this context. better just to declare a new variable.
myApp.factory('LoginFactory', ['$http', function ($http) {
var data;
$http.get('/api/login.json').success(function (d) {
data = d;
});
return {
getData: function () {
return data;
}
};
}]);
you will still have a race issue though, so i would also recommend either promise chaining
myApp.factory('LoginFactory', ['$http', function ($http) {
var promise = $http.get('/api/login.json');
return {
getData: function (callback) {
promise.success(callback);
}
};
}]);
or even a conditional get
myApp.factory('LoginFactory', ['$http', function ($http) {
var data;
return {
getData: function (callback) {
if(data) {
callback(data);
} else {
$http.get('/api/login.json').success(function(d) {
callback(data = d);
});
}
}
};
}]);
The last two approaches require you to rewrite your controller though
myApp.controller('AccountsCtrl', ['$scope', 'Accounts', 'LoginFactory', function($scope, Accounts, LoginFactory){
LoginFactory.getData(function(data) {
$scope.login = data;
console.log('$scope.login: %o', $scope.login);
$scope.accounts = Accounts.index(); //this might have to go here idk
});
}]);
Extending #LoganMurphy answer. Using promise and still adding callbacks is not at all desirable. A better way of writing service could be
myApp.factory('LoginFactory', ['$http', function ($http, $q) {
var data;
return {
getData: function () {
if(data) {
return $q.when(data);
} else {
return $http.get('/api/login.json').then(function(response){
data = response;
return data;
});
}
}
};
}]);
You have an issue with the this keyword and also you not handling the promise from the http.get correctly
I would write it like this:
myApp.factory('LoginFactory', ['$http', function($http){
return {
getData : function(){
return $http.get('/api/login.json');
}
}
}]);
myApp.controller('AccountsCtrl', ['$scope', 'Accounts', 'LoginFactory', function($scope, Accounts, LoginFactory){
$scope.login = LoginFactory.getData().success(function(data){
console.log(data);
console.log('$scope.login: %o', $scope.login);
});
}]);
I find myself doing things like this a lot in my Angular services:
getStats: function() {
var deferred = $q.defer();
$http.get('/stats').success(function(stats) {
deferred.resolve(stats);
});
return deferred.promise;
}
Note that the promise I'm returning resolves to the returned data. It's not a situation where I can use a .success callback.
Is there a simpler way to do this without using $q?
That should work, because $http.get returns promise object,
getStats: function() {
return $http.get('/stats');
}
in your code you use it like this:
someService.getStats().success(successFN);
Create an API service:
app.factory('apiService', ['$http', function($http) {
'use strict';
return {
getStats: function (deviceId) {
return $http.get('/stats');
}
}
}
Then inject the apiCall in your controller and use the getStats method.
app.controller("MyController", ['$scope', 'apiService', '$routeParams', function($scope, apiService, $routeParams) {
'use strict';
angular.extend($scope, {
info: {},
deviceId: $routeParams.deviceId,
loadInfo: function () {
apiService
.getStats($scope.deviceId)
.succes(function (res, statusCode) {
$scope.info = res;
})
.error(function () {
alert('Oh NOS!');
})
}
});
$scope.loadInfo();
}]);
In an AngularJs application, we need to fetch a config json from server. This config is used in several controllers, and there are many controllers will retrieve another resources based on the config.
For now, I'm doing it like this:
angular.module('myApp', [])
.run(function($http, $rootScope) {
$http.get('/public/js/config.json')
.success(function(data) {
$rootScop.config = data;
})
}
.controller('Controller1', function($http, $scope, $rootScope) {
$scope.$watch('config', function() {
if($rootScope.config) {
$http.get('/public/data/' + $rootScope.config.dataSource1 + ".json")
.success(funciton(data) {
$scope.mydata1 = data;
})
}
});
})
.controller('Controller2', function($http, $scope, $rootScope) {
$scope.$watch('config', function() {
if($rootScope.config) {
$http.get('/public/data/' + $rootScope.config.dataSource2 + ".json")
.success(funciton(data) {
$scope.mydata2 = data;
})
}
});
})
You can see I used $watch to watch the $rootScope.config and do something based on it.
It works but I find the code is not very good. Is there any better solution?
PS: We are not using angular routes in this project.
Instead of watching the $rootScope, you could use a service like this:
angular.module('myApp', [])
.factory('appConfig', function ($http) {
return $http.get('/public/js/config.json')
.then(function (resp) {
return resp.data;
});
})
.controller('Controller1', function($http, $scope, appConfig) {
appConfig.then(function (config) {
$http.get('/public/data/' + config.dataSource1 + ".json")
.success(function (data) {
$scope.mydata1 = data;
});
});
})
.controller('Controller2', function($http, $scope, appConfig) {
appConfig.then(function (config) {
$http.get('/public/data/' + config.dataSource2 + ".json")
.success(funciton(data) {
$scope.mydata2 = data;
});
});
});
Hope this helps.
Trying to return data from the factory and logging within the factory outputs the correct data, but once passed to the controller it is always undefined. If I have my factory logic inside the controller it will work fine. So it must be something simple Im missing here?
Application
var app = angular.module('app', []);
app.controller('animalController', ['$log', '$scope', 'animalResource', function($log, $scope, animalResource) {
$scope.list = function() {
$scope.list = 'List Animals';
$scope.animals = animalResource.get(); // returns undefined data
$log.info($scope.animals);
};
$scope.show = function() {};
$scope.create = function() {};
$scope.update = function() {};
$scope.destroy = function() {};
}]);
app.factory('animalResource', ['$http', '$log', function($http, $log) {
return {
get: function() {
$http({method: 'GET', url: '/clusters/xhrGetAnimals'}).
success(function(data, status, headers, config) {
//$log.info(data, status, headers, config); // return correct data
return data;
}).
error(function(data, status, headers, config) {
$log.info(data, status, headers, config);
});
},
post: function() {},
put: function() {},
delete: function() {}
};
}]);
Log Info
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
200 function (name) {
if (!headersObj) headersObj = parseHeaders(headers);
if (name) {
return headersObj[lowercase(name)] || null;
}
return headersObj;
} Object {method: "GET", url: "/clusters/xhrGetAnimals"}
Your get() method in service is not returning anything. The return inside the success callback only returns from that particular function.
return the $http object
Che this example that is how you use the promises and you return the factory then you access the methods injecting the service on your controller
Use dot syntax to access the function you define on the service
'use strict';
var app;
app = angular.module('app.formCreator.services', []);
app.factory('formCreatorService', [
'$http', '$q', function($http, $q) {
var apiCall, bjectArrarContainer, deferred, factory, webBaseUrl, _getFormElementsData;
factory = {};
deferred = $q.defer();
bjectArrarContainer = [];
webBaseUrl = 'https://tools.XXXX_url_XXXXX.com/XXXXXXX/';
apiCall = 'api/XXXXX_url_XXXX/1000';
_getFormElementsData = function() {
$http.get(webBaseUrl + apiCall).success(function(formElements) {
deferred.resolve(formElements);
}).error(function(err) {
deferred.reject(error);
});
return deferred.promise;
};
factory.getFormElementsData = _getFormElementsData;
return factory;
}
]);
then do it like this for example
'use strict';
var app;
app = angular.module('app.formCreator.ctrls', []);
app.controller('formCreatorController', [
'formCreatorService', '$scope', function(formCreatorService, $scope) {
$scope.formElementsData = {};
formCreatorService.getFormElementsData().then(function(response) {
return $scope.formElementsData = response;
});
}
]);