I created this http service:
(function () {
"use strict";
angular.module("inspectionReview").factory("inspectionReviewServices", ["$http", "config", inspectionReviewServices]);
function inspectionReviewServices($http, config) {
var serviceAddress = config.baseUrl + "api/InspectionReview/";
var service = {
getValues: getValues
};
return service;
function getValues(objectId, frequencyId) {
return $http.get(serviceAddress + "getValuesByObjectTypeId/" + objectId + "/" + frequencyId);
}
}
})();
And here I use it in controller to get data:
function checkInspection() {
var frequencyId = 5;
inspectionReviewServices.getValues($scope.object.Id, frequencyId).then(function (result) {
$scope.someData = result.data;
});
}
When I call function checkInspection I need to wait until $scope.someData property is populated by data and only after it populated by data only then further rows can be executed.Currently I get promise and code executed further.
EDIT(according to the Darren's answer):
I changed my service and function that calls service:
function getValues2(objectId, frequencyId) {
return $http.get(serviceAddress + "getValuesByObjectTypeId/" + objectId + "/" + frequencyId).then(function (result) {
return result.data;
});
}
and here is function that calls for service in controller:
function checkInspectionReviewValidety() {
var frequencyId = 5;
return inspectionReviewServices.getValues2($scope.object.Id, frequencyId)
}
But still I dont get desired result.
How can I change checkInspection function to make it wait until $scope.someData property is populated by data?
You can use .then on the $http service method
$http.get(serviceAddress + "getValuesByObjectTypeId/" + objectId + "/" + frequencyId).then(function() {
// Populate items from callback
});
You can't do that. The whole aspect of promises is to handle the async request and execute when the promise is resolved/rejected. If you want some piece of code to execute after data is filled up please move that part of the code into .then block.
Related
i have a controller that calls a function in a service. this, in turn, calls a promise function inside the same service.
the problem is that i can't get the returned value in my controller.
the controller:
function mainFunctionInControlelr() {
some code here...
vm.evtHTTPFactory.getData() // calling the service
.then(function(response) {
console.log("the returned value is " + response.myReturned );
});
}
the service:
factory.getData = function(parm) {
return factory.getABC(parm); // calling another method in the same service
};
factory.getABC = function(parm) {
return $q(function(resolve, reject) {
$http.get(PltConfig.APIPath + '/v1/............', {
params: { inputParm: parm }
})
.success(function (response) {
resolve(response.data.myReturned);
return;
} )
});
};
the issue is that getData, inside the service, is calling getABC, also inside the service. something is lost in the process. I need to have "myReturned" in the controller.
what do i need to put in getData (in the service) to make things work?
thanks a lot.
I would use async await... like this:
in your function getData:
factory.getData = async function(parm) {
var data = await factory.getABC(parm);
return data;
};
in your function controller:
async vm.evtHTTPFactory.getData() {
var myResp = await vm.evtHTTPFactory.getData()
console.log(myResp)}
An example here: https://jsfiddle.net/hernangiraldo89/frv4L2jh/4/
I hope it helps you!
I have a piece of Code in angularjs. If I hard code the value of http response it is displaying the response when I use the http method in angularjs it is not displaying. Whenever request sends to server i get error function. I dont know where I am wrong. Here is the code
(function() {
'use strict';
angular
.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('DemoCtrl', DemoCtrl);
function DemoCtrl($timeout, $q, $log, $http, $scope) {
var self = this;
self.simulateQuery = false;
self.isDisabled = false;
self.repos = loadAll();
self.querySearch = querySearch;
self.selectedItemChange = selectedItemChange;
self.searchTextChange = searchTextChange;
function querySearch(query) {
var results = query ? self.repos.filter(createFilterFor(query)) : self.repos,
deferred;
if (self.simulateQuery) {
deferred = $q.defer();
$timeout(function() {
deferred.resolve(results);
}, Math.random() * 1000, false);
return deferred.promise;
} else {
return results;
}
}
function searchTextChange(text) {
$log.info('Text changed to ' + text);
}
function selectedItemChange(item) {
$log.info('Item changed to ' + JSON.stringify(item));
}
function loadAll() {
$log.info('test');
var repos;
repos = [];
$http.get('http://melkban24.ir/city/json/2').success(function(response) {
$scope.repos = response.data;
});
return repos.map(function(repo) {
repo.value = repo.nameCity.toLowerCase();
$log.info(repo.value);
return repo;
});
}
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(item) {
return (item.value.indexOf(lowercaseQuery) === 0);
};
}
}
})();
$http.get() is asynchronous, so the .success() callback won't be called until after your function has returned. That means loadAll() cannot return the data. Try not to confuse $scope.repos with the local variable repos as they are quite different things.
Don't use the deprecated .success() method at all. Use .then() as it will return a promise which is compatible with other uses of promises in angular.
Move the map code inside the .then callback and if you want loadAll() to return anything make it return the promise that .then() returns. That way anything that calls loadAll() can wait on the promise to complete.
function loadAll() {
return $http.get('http://melkban24.ir/city/json/2').then(function(result){
var repos = result.data.data;
return repos.map(function (repo) {
repo.value = repo.nameCity.toLowerCase();
return repo;
});
$scope.repos = repos;
});
}
Now you have two ways to get at the data: it will appear as the repos value in the scope once it has been retrieved. If used in an angular template the page will show the new data. Or call loadAll() and use the promise to get at the returned data:
loadAll().then(function(repos) { ... });
You should also consider including code for the case where $http.get() fails. Pass it an error callback as well.
Also, as #Rakeschand points out in the comments, the next step should be to move all the $http code out of the controller and into a service. You still end up calling a function that returns a promise, but code to convert the received data into the data you actually want can be removed from the controller.
I think I have a syntax error in my code, but I am not entirely sure. Basically when I call a function on the service, it returns the code rather than the return value of the function.
This is the service ...
(function (){
'use strict';
var products = function($http){
var getProducts = function () {
return $http.get(getDataUrl)
.then(function (response) {
return response.data;
});
};
//Make functions public
return {
getProducts: getProducts
};
};
var module = angular.module("shop");
module.factory("products", products);
module.constant("getDataUrl", "xxx")
}());
This is the controller than invokes the product service ...
(function () {
'use strict';
angular
.module("shop")
.controller("ProductController", ProductController);
function ProductController($scope, cart, $routeParams, products) {
// $scope.product = products.getProducts;
// console.log($scope.product);
var productId = getProductIdFromUrl();
console.log("productId: " + productId);
console.log("products: " + products.getProducts);
function getProductIdFromUrl(){
return $routeParams.productId;
}
}
})();
Now rather than returning the JSON data that I am expecting, the console.log is just printing the the functions code. Anyone any ideas?
The console.log prints the following ...
products: function () {
return $http.get(getDataUrl)
.then(function (response) {
return response.data;
});
}
Yep, you do have a syntax error, right here:
console.log("products: " + products.getProducts);
That should be:
console.log("products: " + products.getProducts());
HOWEVER that is not going to log a list of products, it's going to log a promise object, which is what $http.get().then() returns. You need to re-read the documentation for $http and also read more about promises and how they work. Your code is non-functional as-is. This article explains why: http://blog.ninja-squad.com/2015/05/28/angularjs-promises/
I've created a Factory to retrieve customers:
customerModule.factory("CustomerFactory", ["$http", "DataService", function ($http, dataService) {
var self = this;
self.page = 1;
self.query = "";
var queryFn = function (query) {
self.query = query;
$http.get(dataService.baseURI + "/customers", {
params: {
query: self.query,
page: self.page,
pageSize: 50
}
}).success(function (data) {
return data.result;
});
};
return {
query: queryFn
};
}]);
But when I use it in my controller, it returns undefined, I'm not sure what I'm doing wrong here?
$scope.$watch("query", function () {
if ($scope.query && $scope.query.length > 3) {
console.log(customerFactory.query($scope.query));
}
else if ($scope.query.length < 4) {
$scope.customers = [];
}
});
If you take a close look at your queryFn function you will notice that you're not actually returning anything from it. This means that queryFn will return undefined.
So the first step to fixing your code is to put return in front of $http.
Second step is fixing the way you are calling customerFactory.query function. You expect it to return the value immediately, but $http actually creates an XHR request, and XHR requests are async by default, so you cannot expect customerFactory.query to return the result right away.
If you haven't learned of promises than this is the time to take a look at them, because they are used all over the place, in angular world.
Assuming that you have put return in front of $http, the call to customerFactory.query will actually return a promise object. That promise object has a .then method. This method should be used as:
customerFactory.query($scope.query)
.then(function(customers){
console.log(customers);
});
I have a service that fetches some client data from my server:
app.factory('clientDataService', function ($http) {
var clientDataObject = {};
var cdsService = {
fetch: function (cid) {
//$http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('/clients/stats/' + cid + '/').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
clientDataObject = {'data': response.data, 'currentClientID': cid};
return clientDataObject;
});
// Return the promise to the controller
return promise;
}
};
return cdsService;
});
Then in one controller I do:
//get stats
clientDataService.fetch($scope.id).then(function (response) {
$scope.client_data = {
'statistics': response.data
}
});
Which all works very well. However, I'm trying to do a watch from another controller on that service to update it's scope when the data changes, rather then having to re-kick off the http request:
$scope.$watch('clientDataService.clientDataObject', function (cid) {
alert(cid);
});
I'm just alerting for now, but it never ever triggers. When the page initially loads, it alerts "undefined". I have no errors in the console and all the $injects are fine, but it never seems to recognize that data has changed in the service. Am I doing something wrong in the watch?
Many thanks
Ben
clientDataService.clientDataObject is not part of your controller's scope, so you can't watch for changes on that object.
You need to inject the $rootScope into your service then broadcast the changes to the controllers scopes.
app.factory('clientDataService', function ($rootScope, $http) {
var clientDataObject = {};
var cdsService = {
fetch: function (cid) {
var promise = $http.get('/clients/stats/' + cid + '/').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
clientDataObject = {'data': response.data, 'currentClientID': cid};
$rootScope.$broadcast('UPDATE_CLIENT_DATA', clientDataObject);
return clientDataObject;
});
// Return the promise to the controller
return promise;
}
};
return cdsService;
});
Then in the controller you can listen for the change using:
$scope.$on('UPDATE_CLIENT_DATA', function ( event, clientDataObject ) { });
Another approach can be:
define new service
app.factory('DataSharingObject', function(){
return {};
}
include this new service in controller where we want to store the data
app.factory('clientDataService', function ($http, DataSharingObject) {
DataSharingObject.sharedata = ..assign it here
}
include this new service in controller where we want to access the data
app.factory('clientReceivingService', function ($http, DataSharingObject) {
..use it here... = DataSharingObject.sharedata
}