I can't get my scope variable populated from a object resulted from a service.
here is my service :
app.factory("studentService", ['$http','$q','$localstorage','$state',
function($http,$q,$localstorage,$state) {
return{
getPersonalInfo:function(pi_id)
{
return $http.get(app.baseUrlServer + app.baseUrlUser + '/getpersonalinfo/' + pi_id)
.then(function(response){
if (response.data) {
return response.data;
} else {
// invalid response
return $q.reject(response.data);
}
},function(response){
// invalid response
return $q.reject(response.data);
});
}
}
/* my controller */
var app_ctrl = angular.module('app.controllers');
app_ctrl.controller('MatesprofileController',
['$scope','$stateParams','studentService','$localstorage',
function($scope, $stateParams, studentService , $localstorage) {
$scope.personalInfo=[];
studentService.getPersonalInfo($stateParams.pi_id).then(function(data){
$scope.personalInfo.push(data);
});
}
I can't get my $scope.personalInfo array populated even though I already pushed the data object into personalInfo array.
in fact, when I console.log(data) inside of the .then function, It outputs the data, but when I do the same, just outside of the .then blocks, it shows nothing..
please, help me. I'm totally stuck of this
update
I've done the following :
app.factory("studentService", ['$http', '$q', '$localstorage', '$state',
function($http, $q, $localstorage, $state) {
return {
getPersonalInfo: function(pi_id) {
var defer = $q.defer();
$http.get(app.baseUrlServer + app.baseUrlUser + '/getpersonalinfo/' + pi_id)
.then(function(response) {
if (response.data) {
defer.resolve(response.data);
} else {
// invalid response
defer.reject(response.data);
}
}, function(response) {
// invalid response
defer.reject("Error");
});
return defer.promise;
}
}
}
/* CONTROLLER */
var app_ctrl = angular.module('app.controllers');
app_ctrl.controller('MatesprofileController', ['$scope', '$stateParams', 'studentService', '$localstorage',
function($scope, $stateParams, studentService, $localstorage) {
//$scope.personalInfo=[];
studentService.getPersonalInfo($stateParams.pi_id).then(function(data) {
$scope.data = data;
console.log($scope.data); //this shows up correctly, but it executed latest
});
console.log($scope.data); // this shows up first in the console, but it's empty
}
Still not workgin :(
update
Finally, I get it worked by simply to not using the then() function. because the service returns the actual data instead of promise, thus, on the controller only need to call it as a variable.
example:
$scope.data = studentService.getPersonalInfo($stateParams.pi_id);
voila!, thanks for those who helped me, special thanks to my friends #arwaniali for suggesting me this solution and also all of you who have answered this questions. thanks : )
Your getPersonalInfo is inconsistent in what it returns. If the http call is successful and you get data, you return the actual data rather than a promise. If you want your function to always return a promise, then you should change getPersonalInfo the following way:
getPersonalInfo:function(pi_id) {
var deferred = $q.defer();
$http.get(app.baseUrlServer + app.baseUrlUser + '/getpersonalinfo/' + pi_id)
.then(function(response){
if (response.data) {
deferred.resolve(response.data);
} else {
// invalid response
deferred.reject(response.data);
}
},function(response){
// invalid response
deferred.reject("Error");
});
return deferred.promise;
}
The $http service returns a promise. You should return this promise to your controller, and then test the return data and do the appropriate error handling if necessary.
app.controller('MatesprofileController', ['$scope','studentService', function($scope, studentService ) {
$scope.personalInfo=[];
studentService.getPersonalInfo(123).then(function(data){
if(data !== undefined && data.length > 0)
$scope.personalInfo = data;
else
console.log('handle error');
console.log($scope.personalInfo);
});
}]);
http://plnkr.co/edit/ZzNBT6pDqhqcAseWVX5I?p=preview
Related
I have a service to get (with array) all post from a server. I need to filter this array by id and show only this post in a single page.
In the service I have this code.
.service('PostAPI', function($http) {
this.getAll = function() {
return $http.get("ajax/getAllPosts.php");
}
this.getOne = function(data) {
return $http.get("ajax/searchPost.php?postID=" + data);
}
this.delete = function(data) {
if (confirm("Are you sure to delete this line?")) {
return $http.delete("ajax/deletePost.php?postID=" + data);
}
}
this.update = function(data) {
return $http.put("ajax/updatePost.php?postID" + data);
}
this.create = function() {
return $http.post("ajax/addPost.php");
}
})
In the controller
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
GetPost();
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).success(function(data) {
$scope.post = data;
console.log($scope.post);
});
};
In post HTML I have this.
<div>
<div>{{post.TASK}}</div>
<div>{{post.STATUS}}</div>
<b>Back</b>
</div>
I'm not able to get any data to show in the page, and also, i have no errors in my console. ¿Any idea?
Check your ajax/searchPost.php?postID= api that is this api returning single object or array, If this api returning object than it should work but If you getting array of single element in response of api then in your api success code use first element of array by data[0].
Controller code
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
GetPost();
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).success(function(data) {
$scope.post = data[0];
console.log($scope.post);
});
};
use then instaed of success. .then returns a promise so that you can handle the asynchrounous calls.
Also you are calling the getPost() method before function definition. So it may not get the promise.
call your getPost(), method after the function definition and check, so that it can receive the promise.
.controller("PostControlador", function($scope, $routeParams, PostAPI) {
$scope.title = "Editar post";
function GetPost() {
PostAPI.getOne($routeParams.id).then(function(data) {
$scope.post = data[0];
console.log($scope.post);
});
};
GetPost();
I'm doing a app for Ionic. Based on answers in a question made by me at $http.get not working at .factory, I wrote the following code:
services.js
angular.module('starter.services', [])
.factory('Chats', function($http) {
// Might use a resource here that returns a JSON array
var factory = {
chats: null,
all: function() { return chats; },
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
}
};
$http.get("http://lucassmuller.com/work/projetoblog/api.php?action=posts").then(function(data) {
factory.chats = data;
console.log('data ok');
});
return factory;
});
controllers.js
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope) {})
.controller('ChatsCtrl', function($scope, Chats) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//
//$scope.$on('$ionicView.enter', function(e) {
//});
$scope.chats = Chats.all();
})
.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})
.controller('AccountCtrl', function($scope) {
$scope.settings = {
enableFriends: true
};
});
But when I run it to do a ng-repeat with data, shows an error saying that chats is not defined. How can I fix it?
The request that you make to any HTTP resource won't be resolved right away. It returns a promise object which is literally a promise saying that Hey, I don't know the result right now, but I will give you a result later regardless it succeeds or not. The promise object is resolved in the controller using its .then property which takes two functions as parameters, onSuccess and onFailure.
In your case, this is how you do it.
Factory/Service
.factory('Chats', function($http) {
// returning a promise from the service
var chats = $http.get("http://lucassmuller.com/work/projetoblog/api.php?action=posts");
var factory = {
chats: null,
all: function() { return chats; },
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
}
};
return factory;
});
Controller
.controller('ChatsCtrl', function($scope, Chats) {
// resolving the promise in the controller
Chats.all().then(function (res){ // onSuccess, called when response is successfully recieved
var chats = res.data
console.log(chats);
$scope.chats = chats;
}, function (err){ // onFailure, called when error response
console.log(err);
});
})
Check Angular Documentation for $http promises.
Hello my code for service is:
angular.module('lucho1App').factory('ApiExample', ['$http', '$q', function($http, $q) {
return {
promiseToHaveData: function() {
return $http.get('http://data.colorado.gov/resource/4ykn-tg5h.json').then(function(response) {
var result = response.data;
console.log(result);
return result;
}, function(response) {
console.log('Error has ocurred');
});
}
};
}]);
and my controller is:
angular.module('lucho1App')
.controller('MainCtrl',['$scope', 'ApiExample',function MainCtrl($scope,ApiExample) {
$scope.apiExampl=ApiExample.promiseToHaveData();
console.log($scope.apiExampl);
}]);
the console.log in the service shows output which means that my request is successful but in the controller $scope.apiExampl is undefined where is my mistake?
A promise is asynchrnous, so it will be resolved later and the function in the then will be called at that very moment. The return in the callback permit to change the object passed to the next then call since promise are chainable object.
First you must return the promise object in your service :
return $http.get(...);
Second change your controller like this :
ApiExample.promiseToHaveData().then(function(data){
$scope.apiExampl=data;
});
note that here i do =data because in your service you already extracted the data object from the response
You need to return promise
promiseToHaveData: function() {
return $http.get('http://data.colorado.gov/resource/4ykn-tg5h.json');
}
And handle the success handler in controller
ApiExample.promiseToHaveData().success (function(response) {
$scope.apiExampl = response.data;
console.log($scope.apiExampl);
});
I have following controller code
module.registerController('DemoCtrl', function ($scope, myFactory) {
myFactory.get(function (data) {
console.log(data); /// data is always undefined
});
});
and following the factory which is calling restful webapi
module.registerFactory('myFactory', ['$http',
function ($http) {
function get(callback) {
$http.get('mywebapiurl')
.success(function (response) {
//debugger; data comes back from server
callback(response);
}).error(function (response, status, headers, config) {
callback(response);
});
}
return {
get: get
}
}]);
The factory is calling webapi service and does gets the data back. However in controller the data doesnt get returned.
Am I missing something obvious here? Also not sure if this is the best way to call webservice in angularjs in controller using factory. Any inputs are most welcome.
Thanks,
You want to return a promise instead of passing a callback. As $http.get already returns a promise, you can just return that, or a derived promise that returns the response data directly. By the way, your factory looks like it should be a service instead:
angular.moudule('yourApp')
.service('myService', ['$http', myService]);
function myService($http) {
this.get = function(url) {
return $http.get(url)
.then(function transformData(response){
return response.data;
}).catch(function onError(rejectionResponse){
//Whatever you want to do here
});
}
}
This way myService.get will return a promise you can .then(), .catch() and .finally() on what you want, staying in the frameworks coding style. For example:
var squirrels = [];
myService.get('http://squirrelshop.com/api/squirrels')
.then(function(squirrelsData){
console.log('Got the squirrels!');
squirrels = squirrelsData;
}).catch(function(rejection){
console.warn('Couldnt fetch squirrels. Reason: ' + rejection);
});
controller code
module.registerController('DemoCtrl', function ($scope, myFactory) {
myFactory.get("url").then(function(d) {
console.log(d.data);
}
});
});
factory which is calling restful webapi
module.registerFactory('myFactory', ['$http',
function ($http) {
var apiFactory = {
get:function(url){
return $http.get(url);
}
}
return apiFactory;
}]);
Success and failure in factory
module.registerFactory('myFactory', ['$http',
function ($http) {
var apiFactory = {
get:function(url){
return $http.get(url).then(function(response){
// success
return responce.data;
},function(error){
//failure
return error;
};
}
}
return apiFactory;
}]);
All server data accesses in my page are performed by my RequestFactory provider.
(The RequestFactory uses $http to perform the actual server calls.)
My controller scope has a reference to the list of data returned from the RequestFactory.
My question is that since the RequestFactory calls are asynchronous, and the RequestFactory does not (and should not) have access to the controller scope, what is the proper way for the RequestFactory to hand off the data to the controller?
var requestFactory = {};
angular.module("myApp").factory("RequestFactory", function($http) {
requestFactory.fetch = function() {
$http.get(url).
success(function(data) {
controller.setData(data)
}).
error(function(data, status) {
console.info("fetch Failed. Error code: " + status + " Url:" + url);
}).finally(function() {
controller.setSubmitting(false);
});
};
return requestFactory;
});
You should return the promise from you factory. See below snippet.
.factory("RequestFactory", function($http) {
return {
fetch : function() {
return $http.get(url).then(function(result) {
return result.data;
});
}
}
});
In your controller you should use like
.controller('MainCtrl', function($scope, RequestFactory) {
RequestFactory.fetch().then(function(data)
$scope.foo = data;
});
});
You can do the following :
Service
(function(){
function Service($http){
function get(){
//We return a promise
return $http.get('path_to_url');
}
var factory = {
get: get
};
return factory;
}
angular
.module('app')
.factory('Request', Service);
})();
Controller
(function(){
function Controller($scope, $q, Request) {
var defer = $q.defer();
//Call our get method from the Request Factory
Request.get().then(function(response){
//When we get the response, resolve the data
defer.resolve(response.data);
});
//When the data is set, we can resolve the promise
defer.promise.then(function(data){
console.log(data);
});
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
As you know, $http service return promise, so after that, you can easily combining them.