I'm a beginner in Angular world, and I can't work out why I'm still getting "not defined" error. Here is my code:
angular.module('dopasujApp').factory('getProducts', ['$http', function ($http) {
var dataFactory = {};
dataFactory.sort='ASC';
dataFactory.orderBy='PRODUCT_NAME';
dataFactory.search='a';
dataFactory.filters={};
dataFactory.filters.ATTRIBS=[46,25];
dataFactory.filters.SIZE=[165,40];
getProducts.listProducts = function() {
var request = $http({
method: "POST",
url: "http://******/backend/internalAPI.php?action=getListing&fit=1&limit=10&vendor=20",
headers: {
'Content-Type': 'application/json'
},
data: {
data: dataFactory
}
});
var products = angular.fromJson(request);
return products;
}
return false;
}]);
And here goes my controller (just for testing purposes now).
angular.module('dopasujApp')
.controller('MainCtrl', ['getProducts', '$scope','$rootScope',
function (getProducts, $scope,$rootScope) {
console.log(getProducts.listProducts())
}
]);
getProducts variable in factory is not defined. The name you used before is just informative name for angular
In your factory you are returning "false" as actual result. So angular treats your "false" as result.
It should look like that :
angular.module('dopasujApp').factory('getProducts', ['$http', function ($http) {
var dataFactory = {}, getProducts = {};
dataFactory.sort='ASC';
dataFactory.orderBy='PRODUCT_NAME';
dataFactory.search='a';
dataFactory.filters={};
dataFactory.filters.ATTRIBS=[46,25];
dataFactory.filters.SIZE=[165,40];
getProducts.listProducts = function() {
return $http({
method: "POST",
url: "http://******/backend/internalAPI.php?action=getListing&fit=1&limit=10&vendor=20",
headers: {
'Content-Type': 'application/json'
},
data: {
data: dataFactory
}
});
}
return getProducts;
}]);
Controller
angular.module('dopasujApp').controller('MainCtrl', ['getProducts', '$scope','$rootScope',
function (getProducts, $scope,$rootScope) {
getProducts.listProducts().then(function(res) {
console.log(res.data);
});
}
]);
EDIT:
Also note, that $http returns promise, but not actual query result, updated my example accordingly
try like this
var yourapp = angular.module('dopasujApp', []); //your defining your app first
yourapp.factory('getProducts', function ($http)
{
return {
//write your factory methods
};
});
you controller should be like below
yourapp.controller('MainCtrl', function PostController($scope, getProducts, $compile)
{
//here your controller methods
});
Related
I want to create a global variable (httpTimeout) initialize at the start, contains a Long value returned by a synchrone call Rest Service and used it in different service
(
function () {
'use strict';
angular
.module('module')
.factory('MyService', function (
$http,
$q
){
var service = {};
var httpTimeout = function() {
return $http({
method: 'GET', '.../rest/getHttpTimeOut'
}).then(function (response) {
return response.data;
}).catch(function (err) {
return 30000;
});
};
service.myService1= function (Model) {
return $http({
method: 'POST', '..../rest/callRestService1',
data: Model, timeout : httpTimeout
}).then(function (response) {
return response.data;
});
};
service.myService2= function (Model) {
return $http({
method: 'POST', '..../rest/callRestService2',
data: Model, timeout : httpTimeout
}).then(function (response) {
return response.data;
});
};});
My rest service
#RequestMapping(value = "/getHttpTimeOut", method = RequestMethod.GET)
#ResponseBody
public long getHttpTimeOutValue() {
return timeoutValue;
}
how i can retrieve this value globally (httpTimeout) for use in other services
Thank you for your help
if your question is how to do something on application start :
look at that
After your application start you can use another service to store the value.
Also if you want to apply this comportement for all request take a look to interceptor
How can I return the APIData.map and not the default success APIdata using $http.jsonp?
LangDataService Constructor:
languages.LangDataService = function($http, $q) {
this.langDefer = $q.defer();
this.isDataReady = this.langDefer.promise;
};
languages.LangDataService.prototype.getApi = function() {
return this.isDataReady = this.http_.jsonp(URL, {
params: {}
})
.success(function(APIData) {
return APIData.map(function(item){
return item + 1; //just an example.
});
});
};
A Ctrl using LandDataService:
languages.LanguageCtrl = function(langDataService) {
languages.langDataService.isDataReady.then(function(data){
console.log('whooo im a transformed dataset', data);
});
}
Use then instead of success in getApi function.
Try a version of the following:
https://jsfiddle.net/L2ndft4w/
// define the module for our AngularJS application
var app = angular.module('App', []);
app.factory('LangDataService', function($q,$http) {
return {
getApi: function() {
var defer= $q.defer();
$http({
url: 'https://mysafeinfo.com/api/data?list=zodiac&format=json&alias=nm=name',
dataType: 'json',
method: 'GET',
data: '',
headers: {
"Content-Type": "application/json"
}
}).
success(function (data) {
defer.resolve(data.map(function(item){
return item.name;
}));
})
return defer.promise;
}
};
});
// invoke controller and retrieve data from $http service
app.controller('DataController', function ($scope, LangDataService) {
LangDataService.getApi().then(function(data){
$scope.data = JSON.stringify(data, null, 2);
});
});
Returns:
[
"Aquarius",
"Aries",
"Cancer",
"Capricorn",
"Gemini",
"Leo",
"Libra",
"Ophiuchus",
"Pisces",
"Sagittarius",
"Scorpio",
"Taurus",
"Virgo"
]
Although, since $http is already a promise, there's probably a shorter way to do this... ($q.when?)
I am trying to decorate the returned data from a angular $resource with data from a custom service.
My code is:
angular.module('yoApp')
.service('ServerStatus', ['$resource', 'ServerConfig', function($resource, ServerConfig) {
var mixinConfig = function(data, ServerConfig) {
for ( var i = 0; i < data.servers.length; i++) {
var cfg = ServerConfig.get({server: data.servers[i].name});
if (cfg) {
data.servers[i].cfg = cfg;
}
}
return data;
};
return $resource('/service/server/:server', {server: '#server'}, {
query: {
method: 'GET',
isArray: true,
transformResponse: function(data, header) {
return mixinConfig(angular.fromJson(data), ServerConfig);
}
},
get: {
method: 'GET',
isArray: false,
transformResponse: function(data, header) {
var cfg = ServerConfig.get({server: 'localhost'});
return mixinConfig(angular.fromJson(data), ServerConfig);
}
}
});
}]);
It seems I am doing something wrong concerning dependency injection. The data returned from the ServerConfig.get() is marked as unresolved.
I got this working in a controller where I do the transformation with
ServerStatus.get(function(data) {$scope.mixinConfig(data);});
But I would rather do the decoration in the service. How can I make this work?
It is not possible to use the transformResponse to decorate the data with data from an asynchronous service.
I posted the solution to http://jsfiddle.net/maddin/7zgz6/.
Here is the pseudo-code explaining the solution:
angular.module('myApp').service('MyService', function($q, $resource) {
var getResult = function() {
var fullResult = $q.defer();
$resource('url').get().$promise.then(function(data) {
var partialPromises = [];
for (var i = 0; i < data.elements.length; i++) {
var ires = $q.defer();
partialPromisses.push(ires);
$resource('url2').get().$promise.then(function(data2) {
//do whatever you want with data
ires.resolve(data2);
});
$q.all(partialPromisses).then(function() {
fullResult.resolve(data);
});
return fullResult.promise; // or just fullResult
}
});
};
return {
getResult: getResult
};
});
Well, Its actually possible to decorate the data for a resource asynchronously but not with the transformResponse method. An interceptor should be used.
Here's a quick sample.
angular.module('app').factory('myResource', function ($resource, $http) {
return $resource('api/myresource', {}, {
get: {
method: 'GET',
interceptor: {
response: function (response) {
var originalData = response.data;
return $http({
method: 'GET',
url: 'api/otherresource'
})
.then(function (response) {
//modify the data of myResource with the data from the second request
originalData.otherResource = response.data;
return originalData;
});
}
}
});
You can use any service/resource instead of $http.
Update:
Due to the way angular's $resource interceptor is implemented the code above will only decorate the data returned by the $promise and in a way breaks some of the $resource concepts, this in particular.
var myObject = myResource.get(myId);
Only this will work.
var myObject;
myResource.get(myId).$promise.then(function (res) {
myObject = res;
});
I have the following code in the controller.js,
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = dataService.getData();
});
But, I think I m probably making a mistake with CORS related issue. Can you please point me to the correct way to make this call? Thanks much!
First, your success() handler just returns the data, but that's not returned to the caller of getData() since it's already in a callback. $http is an asynchronous call that returns a $promise, so you have to register a callback for when the data is available.
I'd recommend looking up Promises and the $q library in AngularJS since they're the best way to pass around asynchronous calls between services.
For simplicity, here's your same code re-written with a function callback provided by the calling controller:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function(callbackFunc) {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, call our callback
callbackFunc(data);
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData(function(dataResponse) {
$scope.data = dataResponse;
});
});
Now, $http actually already returns a $promise, so this can be re-written:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
// $http() returns a $promise that we can add handlers with .then()
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(dataResponse) {
$scope.data = dataResponse;
});
});
Finally, there's better ways to configure the $http service to handle the headers for you using config() to setup the $httpProvider. Checkout the $http documentation for examples.
I suggest you use Promise
myApp.service('dataService', function($http,$q) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
deferred = $q.defer();
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, we can resolve promise and we can access it in controller
deferred.resolve();
}).error(function(){
alert("error");
//let the function caller know the error
deferred.reject(error);
});
return deferred.promise;
}
});
so In your controller you can use the method
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
promises are powerful feature of angularjs and it is convenient special if you want to avoid nesting callbacks.
No need to promise with $http, i use it just with two returns :
myApp.service('dataService', function($http) {
this.getData = function() {
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data;
}).error(function(){
alert("error");
return null ;
});
}
});
In controller
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
Try this
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
Just setting useXDomain = true is not enough. AJAX request are also send with the X-Requested-With header, which indicate them as being AJAX. Removing the header is necessary, so the server is not rejecting the incoming request.
So you need to use what we call promise. Read how angular handles it here, https://docs.angularjs.org/api/ng/service/$q. Turns our $http support promises inherently so in your case we'll do something like this,
(function() {
"use strict";
var serviceCallJson = function($http) {
this.getCustomers = function() {
// http method anyways returns promise so you can catch it in calling function
return $http({
method : 'get',
url : '../viewersData/userPwdPair.json'
});
}
}
var validateIn = function (serviceCallJson, $q) {
this.called = function(username, password) {
var deferred = $q.defer();
serviceCallJson.getCustomers().then(
function( returnedData ) {
console.log(returnedData); // you should get output here this is a success handler
var i = 0;
angular.forEach(returnedData, function(value, key){
while (i < 10) {
if(value[i].username == username) {
if(value[i].password == password) {
alert("Logged In");
}
}
i = i + 1;
}
});
},
function() {
// this is error handler
}
);
return deferred.promise;
}
}
angular.module('assignment1App')
.service ('serviceCallJson', serviceCallJson)
angular.module('assignment1App')
.service ('validateIn', ['serviceCallJson', validateIn])
}())
Using Google Finance as an example to retrieve the ticker's last close price and the updated date & time. You may visit YouTiming.com for the run-time execution.
The service:
MyApp.service('getData',
[
'$http',
function($http) {
this.getQuote = function(ticker) {
var _url = 'https://www.google.com/finance/info?q=' + ticker;
return $http.get(_url); //Simply return the promise to the caller
};
}
]
);
The controller:
MyApp.controller('StockREST',
[
'$scope',
'getData', //<-- the service above
function($scope, getData) {
var getQuote = function(symbol) {
getData.getQuote(symbol)
.success(function(response, status, headers, config) {
var _data = response.substring(4, response.length);
var _json = JSON.parse(_data);
$scope.stockQuoteData = _json[0];
// ticker: $scope.stockQuoteData.t
// last price: $scope.stockQuoteData.l
// last updated time: $scope.stockQuoteData.ltt, such as "7:59PM EDT"
// last updated date & time: $scope.stockQuoteData.lt, such as "Sep 29, 7:59PM EDT"
})
.error(function(response, status, headers, config) {
console.log('### Error: in retrieving Google Finance stock quote, ticker = ' + symbol);
});
};
getQuote($scope.ticker.tick.name); //Initialize
$scope.getQuote = getQuote; //as defined above
}
]
);
The HTML:
<span>{{stockQuoteData.l}}, {{stockQuoteData.lt}}</span>
At the top of YouTiming.com home page, I have placed the notes for how to disable the CORS policy on Chrome and Safari.
When calling a promise defined in a service or in a factory make sure to use service as I could not get response from a promise defined in a factory. This is how I call a promise defined in a service.
myApp.service('serverOperations', function($http) {
this.get_data = function(user) {
return $http.post('http://localhost/serverOperations.php?action=get_data', user);
};
})
myApp.controller('loginCtrl', function($http, $q, serverOperations, user) {
serverOperations.get_data(user)
.then( function(response) {
console.log(response.data);
}
);
})
I have implemented angular $resource with custom functions and parameters as follows:-
.factory('CandidateService', ['$resource', function ($resource) {
return $resource("api/:action/:id", {},
{
'getCandidates': { method: "GET", params: { action: "Candidate" }, isArray: true },
'getCandidate': { method: 'GET', params: { action: "Candidate", id: "#id" } }
});
}]);
And I am consuming this in the controller as follows:-
.controller('Controller', ['CandidateService', function ($scope, CandidateService) {
$scope.candidateList = [];
CandidateService.getAll(function (data) {
$scope.candidateList = data;
});
}]);
This is working absolutely fine. Now I need to cache the data from the api into the CandidateService Factory so it is not loaded eveytime I move between the controllers.
So I thought i would do something as follows:-
.factory('CandidateService', ['$resource', function ($resource) {
var Api = $resource("api/:action/:id", {},
{
'getCandidates': { method: "GET", params: { action: "Candidate" }, isArray: true },
'getCandidate': { method: 'GET', params: { action: "Candidate", id: "#id" } }
});
var candidateDataLoaded = false;
var candidateData = [];
return {
getCandidates: function () {
if (!candidateDataLoaded) {
Api.getAll(function (data) {
angular.copy(data, candidateData);
});
}
return candidateData;
}
}
}]);
But I just cant get this to work. I think it has something to do with angular factory being a singleton.
Is my approach correct to implement the caching?
You can use the $cacheFactory object.
See : http://docs.angularjs.org/api/ng.$cacheFactory
You can cache $http request like that :
var $httpDefaultCache = $cacheFactory.get('$http');
If you want to retrieve a specific url in cache do :
var cachedData = $httpDefaultCache.get('http://myserver.com/foo/bar/123');
$You can clear the cache too :
$httpDefaultCache.remove('http://myserver.com/foo/bar/123');
or :
$httpDefaultCache.removeAll();
Complete post here : Power up $http with caching