Angularjs http call and saving received data to the controller instance - angularjs

app.controller('sampleCtrl', function($scope, $http, nonService){
this.someVar = 'Hello World';
$http.post('funcsPHP/2.0/getConditionProductService.php',
{ 'product' : angular.toJson(this.productObj) }).
success(function(data, status, headers, config) {
$scope.saveData = data; // works fine
this.saveData = data // 'this' doesnt refer to the controller 'sampleCtrl' anymore, but to the $http instance, right ?
}).
error(function(data, status, headers, config) {
console.log("ERROR");
// log error
});
});
I am aware that I am able to save data to the $scope, but I would like to know how I would be able to save data to a controller variable, such as 'this.someVar'. Do I have to inject an instance of my controller into the $http ?
Cheers !

There are a few ways.
The easiest is to just assign a variable to point to the this value in your controller. The most common names are _this, self, and that.
So you get:
app.controller('sampleCtrl', function($scope, $http, nonService){
this.someVar = 'Hello World';
var self = this;
$http.post('funcsPHP/2.0/getConditionProductService.php',
{ 'product' : angular.toJson(this.productObj) }).
success(function(data, status, headers, config) {
$scope.saveData = data;
self.saveData = data;
})
.error(function(data, status, headers, config) {
console.log("ERROR");
// log error
});
});
The other way is to use Function#bind() for your success handler to set this correctly inside it.
That would give you:
app.controller('sampleCtrl', function($scope, $http, nonService){
this.someVar = 'Hello World';
$http.post('funcsPHP/2.0/getConditionProductService.php',
{ 'product' : angular.toJson(this.productObj) }).
success((function(data, status, headers, config) {
$scope.saveData = data;
this.saveData = data;
}).bind(this))
.error(function(data, status, headers, config) {
console.log("ERROR");
// log error
});
});

Use "Controller As" way of accessing your controllers instance variables:
<div ng-controller="sampleCtrl as ctrl">
{{ctrl.someVar}}
</div>

Related

AngularJS : service not returning value

I'm trying to write an Angular service and it seems like there is something missing. My problem is its not returning any value to my Angular controller
getPrepTimes() method is not returning the http data
But when I check the network (via Chrome dev tools) it will correctly call the external api and return a json object as a response
#my service
'use strict';
angular.module('recipeapp')
.service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes();
function getPrepTimes(){
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function (data, status, header, config){
return data;
});
};
}
]);
#controller
'use strict';
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime;
}]);
When I checked the method getPrepTimes() with returning a string it works. What could be missing here?
A couple things are wrong with the above. You assign this.prepTime to getPrepTimes(). The () there will invoke getPrepTimes immediately, and not when you actually call it! You also need to utilize callbacks to get your data back and use it:
angular.module('recipeapp').service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes;
function getPrepTimes(callback) {
$http({
url: '/prep_times/index.json',
method: 'GET'
}).success(function (data, status, header, config){
callback(data);
});
};
}]);
And now use it like so:
prepTimeService.prepTime(function(data) {
$scope.prep_time = data;
});
Calls to the $http service are async, which means you need to return a promise (and not a value):
this.prepTime = function() {
return $http({
url: '/prep_times/index.json',
method: 'GET'
});
};
And on the controller:
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime()
.success(function (data, status, header, config){
$scope.someVar = data;
});
}]);
Wrap answer with promise:
var self = this;
var deferred = $q.defer();
self.getPrepTimes = function() {
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function(data, status, headers, config) {
if (data.error === undefined) {
deferred.resolve(data);
} else {
if (data.error !== undefined) {
} else {
deferred.reject(data);
}
}
}).error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
In controller call it:
prepTimeService.getPrepTimes().then(function(result) {
$scope.prep_time = result;
},
function(error) {
// show alert
});

Accessing data within a promise

I wan't to access the data in my controller just after the call to getAllMenuItems function:
x.factory('menuItemsData', function($http, $q){
return {
getAllMenuItems: function(){
var deferred=$q.defer();
$http({method: 'GET', url: 'data/MenuItems.json'}).
success(function(data, status, headers, config){
deferred.resolve(data);
}).
error(function(data, status, headers, config){
deferred.reject(status);
});
return deferred.promise;
}
};
});
app.controller('ctrl', function($scope, menuItemsData){
menuItemsData.getAllMenuItems().success(function(data){
console.log(data);
});
});
In this way:
app.controller('myCtrl', function($scope, myService){
myService.getAllMenuItems().success(function(res){
// access the response here.
$scope.menuItems = res.Items; // assign the menuitems.
})
});
You need to get the data from a promise like this:
menuItemsData.getAllMenuItems().then(function(data){
console.log(data);
});
menuItemsData.getAllMenuItems().then(
function(res){
//success callback
},
function(error){
//failure callback
}
);

using promise in http request in angular

the problem is when I use $http or $resource to retrieve data, it is successfully retrieve and bind to view, but when I use promise the data come to client but it does not bind to the view.
here is my code:
//view
<div class="pull-left span6" >
<h3>{{Name}}</h3>
<ul>
<li ng-repeat="type in typeList">
<span>{{type.Title}}</span>
</li>
</ul>
//controller
var proxyControllers = angular.module('httpProxyControllers', []);
proxyControllers.controller('TypeListController',
function TypeListController($scope, typeListData) {
$scope.Name = 'Type List Addresses';
$scope.typeList = typeListData.getTypeList();
$scope.typeList.then(function(data){
console.log('data received');
console.log(data);
},function(status){
console.log(status);
});
});
//service
var proxyServices = angular.module('httpProxyServices', ['ngResource']);
proxyServices.factory('typeListData' , function($http, $q){
return{
getTypeList : function(){
var deferred = $q.defer();
$http({method : 'GET' , url: '/data/getTypeList'})
.success(function(data, status, headers, config){
deferred.resolve(data);
})
.error(function(data, status, headers, config){
deferred.reject(status);
});
return deferred.promise;
}
}
});
in then block of controller when i log data to console, it shows that data comes back successfully but nothing happen to my view and my view shows nothing actually.
thanks in advance,
You need to assign data to $scope.typeList
//initialize with empty array
$scope.typeList = [];
typeListData.getTypeList().then(function(data){
//initialize with received data
$scope.typeList = data;
console.log('data received');
console.log(data);
},function(status){
console.log(status);
});

How can I make a function call depend on completion of two $http calls in AngularJS?

In my controller I have the following calls:
optionService.init($scope);
optionService.getSubjects1($scope);
optionService.getSubjects2($scope);
optionService.getAbc($scope);
Here's the code for the optionService:
angular.module('common')
.factory('optionService',
['$http',function ($http) {
var factory = {
init: function ($scope) {
$scope.option = {};
},
getSubjects1: function ($scope) {
var url = '/api/Subject1/GetSelect';
$scope.loading++;
$http.get(url)
.success(function (data, status, headers, config) {
$scope.option.subjects1 = data;
$scope.loading--;
})
.error(function (data, status, headers, config) {
$scope.loading--;
alert("Error: No data returned from " + url);
});
},
getSubjects2: function ($scope) {
var url = '/api/Subject2/GetSelect';
$scope.loading++;
$http.get(url)
.success(function (data, status, headers, config) {
$scope.option.subjects2 = data;
$scope.loading--;
})
.error(function (data, status, headers, config) {
$scope.loading--;
alert("Error: No data returned from " + url);
});
},
}
return factory;
}]);
Is there a way that I could make the call to optionService.getAbc depend on the completion of both the getSubjects1 and getSubjects2 calls? I will also soon be using Angular 1.2 if this makes any difference.
$q.all(promises) lets you combine multiple promises in to one:
optionService.getAbc = function($scope) {
$q.all([
optionService.getSubjects1($scope),
optionService.getSubjects2($scope)
])
.then(function() {
//...
});
}
Edit. Yes, you need to return promises from your getSubjects functions. To keep code changes to bare minimum, you could do something like this:
optionService.getSubjects1($scope) {
var url = '/api/Subject1/GetSelect';
$scope.loading++;
return $http.get(url)
.then(function (data, status, headers, config) {
$scope.option.subjects1 = data;
$scope.loading--;
}, function (data, status, headers, config) {
$scope.loading--;
alert("Error: No data returned from " + url);
});
}
With $http.then() you create a new promise that can be combined with other promises in getAbc()
You should rewrite your getSubject1 and getSubject2 to return promise. Also passing the $scope to the method and updating the scope from the service method is not a good way of doing things. You service methods should return data which assignable in your code. This makes your services more usable and readable.
If you change getSubject1 and getSubject2 in lines of
getSubjects1: function () {
var url = '/api/Subject1/GetSelect';
return $http.get(url);
}
In your controller you can do
$q.all([
optionService.getSubjects1(),
optionService.getSubjects2()
])
.then(function([data1, data2]) {
//use data1 to update scope for subject1
// use data2 to update scope for subject2
//call any service method.
});

AngularJS $http is not defined

I'm pretty new to with AngularJS. When I'm calling $http.get I get a $http is not defined error.
This is the content of my Module:
var demoApp = angular.module('demoApp', []);
demoApp.config(function ($routeProvider) {
$routeProvider.
when('/view1',
{
controller: 'SimpleController',
templateUrl: 'View1.html'
}).
when('/view2',
{
controller: 'SimpleController',
templateUrl: 'View2.html'
})
.otherwise({ redirectTo: '/view1' });
});
demoApp.factory('simpleFactory', function () {
var factory = {};
factory.getAnnounces = function ($http) {
$http.post("http://localhost:57034/Announce/GetAllAnnounces")
.success(function (data, status, headers, config) {
return data;
}).error(function (data, status, headers, config) {
return status;
});
};
return factory;
});
demoApp.controller('SimpleController', function ($scope,simpleFactory) {
$scope.announces = [];
init();
function init()
{
$scope.announces= simpleFactory.getAnnounces();
}
});
What am I missing here? Cheers.
You need to review your code as follows:
demoApp.factory('simpleFactory', ['$http', function ($http) {
return {
getAnnounces: function () {
$http.post("http://localhost:57034/Announce/GetAllAnnounces")
.success(function (data, status, headers, config) {
return data;
}).error(function (data, status, headers, config) {
return status;
});
}
};
}]);
There's no need to pass the $http variable in the getAnnounces method definition, because it is defined already in the scope of the factory function.
I am using parameter aliasing for AngularJS in order to avoid issues with minifiers, see 'A note on minification' on the AngularJS web site.
Note anyway that $http.post.success and $http.post.error are asynchronous and you won't be able to get the data unless you're using promises ($q), see here. Therefore you could change the code this way:
demoApp.factory('simpleFactory', ['$http', '$q', function ($http, $q) {
return {
getAnnounces: function () {
var deferred = $q.defer();
$http.post("http://localhost:57034/Announce/GetAllAnnounces")
.success(function (data, status, headers, config) {
deferred.resolve(data);
}).error(function (data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
}
};
}]);
And in the SimpleController:
demoApp.controller('SimpleController', ['simpleFactory', '$scope', function (simpleFactory, $scope) {
$scope.announces = [];
simpleFactory.getAnnounces()
.then(function(data) {
// call was successful
$scope.announces = data;
}, function(data) {
// call returned an error
$scope.announces = data;
});
}]);

Resources