I'm getting the following syntax error in the console while trying to get data from 'openweathermap'
Uncaught SyntaxError: Unexpected token :
Here is the JS file :
var app = angular.module('App', ['ngResource']);
app.factory('weatherService', function($http) {
return {
getWeather: function() {
var weather = '';
// if (!!prmSearchValue) {
// var searchValue = prmSearchValue;
$http.jsonp('https://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=c19bc0731cec50456576c7b36a675ca7&mode=json').success(function(data) {
weather = 3232;
});
// }
/* else {
weather = {};
} */
return weather;
}
};
});
//Eilat,Israel
app.controller('httpAppCtrlr', function($scope, weatherService) {
$scope.searchText = '';
$scope.searchWeather = function() {
var prmSearchValue = $scope.searchText;
$scope.weather = weatherService.getWeather();
};
});
It looks as if the data that returns is broken in some way..
Fiddle
Use $http Get instead of JSONP. Better way to handle the error is using .then, Change your Factory as follows,
app.factory('weatherService', function ($http) {
return {
getWeather: function () {
var weatherForcast = {};
$http({
method: 'GET',
url: "https://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=c19bc0731cec50456576c7b36a675ca7"
}).then(function successCallback(response) {
angular.extend(weatherForcast, response.data);
}, function errorCallback(response) {
alert('API call failed, possibly due to rate limiting or bad zip code.');
});
return weatherForcast;
}
};
});
WORKING FIDDLE
In AngularJS jsonp, you need to append callback=JSON_CALLBACK to the url. (I'll assume there is a reason you're using jsonp instead of get.)
Replace
https://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=c19bc0731cec50456576c7b36a675ca7&mode=json
with
https://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=c19bc0731cec50456576c7b36a675ca7&mode=json&callback=JSON_CALLBACK
Fiddle
Related
I am trying to Unit Test an AngularJS HTTP Service with the help of Karma-Jasmine.
But I am facing the following Error from Karma:
Error: Unexpected request: GET app/license/license.html
I Googled and found out that it has something to do with ui-router.
The following StackOverflow Link: (UI-router interfers with $httpbackend unit test, angular js) suggests some Answers, but none of them works for me and the Error remains the same.
I am posting my code below for reference:
licensedata.service.js
(function () {
"use strict";
angular
.module("app")
.factory("licenseDataService", licenseDataService)
licenseDataService.$inject = ["$http"];
function licenseDataService($http) {
return {
getLicenseSpecs: getLicenseSpecs
};
function getLicenseSpecs() {
return $http.get("http://localhost:8080/?command=print-spec")
.then(success)
.catch(fail);
function success(response) {
return response.data;
}
function fail(e) {
return e.data;
}
}
}
})();
licensedata.service.spec.js
describe("LICENSE DATA SERVICE", function () {
var licenseDataService;
var httpBK;
beforeEach(angular.mock.module("app"));
beforeEach(angular.mock.module(function ($urlRouterProvider) {
$urlRouterProvider.deferIntercept();
}));
beforeEach(inject(function (_licenseDataService_, $httpBackend) {
licenseDataService = _licenseDataService_;
httpBK = $httpBackend;
}));
it("Test License Key", function () {
var returnData = {};
httpBK.expectGET("http://localhost:8080/?command=print-spec").respond(returnData);
var returnedPromise = licenseDataService.getLicenseSpecs();
var result;
returnedPromise.then(function (response) {
result = response.data;
});
httpBK.flush();
});
});
Any help will be greatly appreciated.
I have an AngularJs application working with components and several modules. I created a plunker example to present my problem here.
I have my NavbarComponent where I declared my Controller where I inject my service called NavbarService.
In the NavbarService, I inject a factory resource to make my Rest call, once this call is made I'm trying to made some treatment on the response before returning it back to the controller, in this example I just apply a simple filter on it, but it doesn't work. If I omit my treatment and return only the categories, the code works and you can visualize a list of two.
I can make my treatment in the controller but this is a bad practice 'cause I believe it should be done in the Service, secondly since it's an asynchronous response I must do something like this to make it work, which is really really ugly:
navbarService.getCategories().$promise.then(function (response) {
console.log("controller", response[0].category);
vm.categories = categoryFilter(response[0].category);
}, function (error) {
console.log("an error occured");
});
Can someone please guide me through this, I'm out of solutions. Thank you
Another simple way is to pass a callback function to service from you component like this
'use strict';
angular.module('navbar').component('appNavbar', {
templateUrl: "navbar.template.html",
controller: [ 'navbarService', function appNavbarController(navbarService) {
var vm = this;
navbarService.getCategories(function(data){
// this will be called when service will get the response and filter function has filtered the response
vm.categories = data;
});
}]
});
Now service should be like this
'use strict';
angular.module('navbar').service('navbarService', ['categoryResourceService', 'categoryFilter', function(categoryResourceService, categoryFilter) {
var vm = this;
vm.getCategories = function(callback) {
categoryResourceService.query(function(response) {
console.log("[NavbarService] response:", response);
callback(categoryFilter(response));
}, function(error) {
console.log("[NavbarService] error:", error);
});
//return vm.categories;
}
}]);
Filter will be like this
'use strict';
angular.module('navbar').filter('category', function() {
return function(categories) {
var categoryIds = ['World'];
var result = [];
angular.forEach(categoryIds, function (categoryId) {
angular.forEach(categories, function (category) {
if (category.name == categoryId) {
console.log("Match");
result.push(category);
}
});
});
return result;
};
});
Your filter should be like this and it should be called in transformResponse in $resource query instead of service, i hope this will help you
'use strict';
angular.module('navbar').filter('category', function() {
return function(categories) {
var categoryIds = ['World'];
var result = [];
angular.forEach(categoryIds, function (categoryId) {
angular.forEach(categories, function (category) {
if (category.name == categoryId) {
console.log("Match");
result.push(category);
}
});
});
return result;
};
});
Your categoryResource.service should be like this
angular.module('shared').factory('categoryResourceService',
['$resource','categoryFilter', function($resource, categoryFilter) {
var provider = "categories.json";
var params = {
id: '#id'
};
return $resource(provider, params, {
query: {
isArray: true,
method: 'GET',
params: {},
transformResponse: function(categories) {
var results = categoryFilter(angular.fromJson(categories));
console.log("[categoryResourceService] filtered response:", results);
return results;
}
}
});
}]);
navbar.service should be like this simply
'use strict';
angular.module('navbar')
.service('navbarService', [ 'categoryResourceService', function (categoryResourceService) {
var vm = this;
vm.getCategories = function(){
vm.categories = categoryResourceService.query(function(response){
console.log("[NavbarService] response:", response);
}, function(error){
console.log("[NavbarService] error:", error);
});
return vm.categories;
}
}]);
And components like this
'use strict';
angular.module('navbar').component('appNavbar', {
templateUrl: "navbar.template.html",
controller: [ 'navbarService', function appNavbarController(navbarService) {
var vm = this;
vm.categories = navbarService.getCategories();
}]
});
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 newbie in angularjs and I'm trying to create new provider. This is my code:
myApp.provider('$Data', function() {
this.URL = 'http://maps.googleapis.com/maps/api/geocode/json?address=Singapore, SG, Singapore, 153 Bukit Batok Street 1&sensor=true';
this.$get = $get;
$get.$inject = ['$http', '$q'];
function $get($http, $q) {
var that = this;
return {
isConnected: function() {
var bIsConnected = 'Default';
$http({method: 'GET', url:that.URL}).then(function (data) {
bIsConnected = 'Yes';
alert('Run this code!');
}, function (data) {
bIsConnected = 'No';
});
return bIsConnected;
}
}
}
});
Jsfiddle demo:
http://jsfiddle.net/0udm9/9dPsb/6/
After I run $Data.isConnected(), the result is always 'Default' although browser show the alert box. I think it's from success function is not of $get. And I have to use provider, not service or factory for this case. Can I do anything to fix this issue?
Thanks,
You have to use promise in your code.
DEMO
Provider:
isConnected: function() {
var deferred = $q.defer();
$http.get(that.url).then(function(res) {
deferred.resolve('Yes');
console.log('example:success', res);
}, function(err) {
deferred.resolve('No');
console.log('example:error', err);
});
return deferred.promise;
}
Controller:
$Data.isConnected().then(function(data) {
$scope.data = data;
});
// UPD
You must use objects if you need to use return values with async code.
DEMO
// UPD 2
FRESH DEMO LINK
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I got this angular factory:
var productApp = angular.module('productApp', ['ngRoute', 'LocalStorageModule', 'angularSlideables', 'ui.bootstrap']);
productApp.factory('productFactory', function($http, localStorageService, $q) {
var factory = {};
factory.getProductById = function(prod_id) {
if(prod_id !== '') {
$http({
url: 'rest/message/getProductById/' + prod_id,
method: 'GET'
}).success(function(data, status) {
return data;
}).error(function(data, status){
// do nothing
});
}else {
alert("There was an error while passing the ID. Please refresh the page and try again");
}
}
return factory;
});
Injecting the factory in a controller and calling to the "getProductById" function:
productApp.controller('ModalInstanceCtrl', function ($scope, $modalInstance, productFactory, prodId) {
console.log("this is the prod id " + prodId);
// search product in the database
$scope.prod = productFactory.getProductById(prodId);
console.log($scope.prod);
$scope.ok = function () {
console.log($scope.prodData);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
Now, don't know what's wrong with it... the function RETURNS the data because i did a console.log(data) and saw all the response, but in the controller if i inspect the $scope.prod, it's undefined. It's not returning the data back from the function.
(Just in case you guys ask, the "prodId" in the controller parameter is fine, and retrieving that from another controller)
How can i solve this? :(
Thanks in advance.
The pattern I have used to solve this problem is to pass in the success & error callback functions to the factory... like this:
var productApp = angular.module('productApp', ['ngRoute', 'LocalStorageModule', 'angularSlideables', 'ui.bootstrap']);
productApp.factory('productFactory', function($http, localStorageService, $q) {
var factory = {};
factory.getProductById = function(prod_id, successCallback, errorCallback) {
if(prod_id !== '') {
$http({
url: 'rest/message/getProductById/' + prod_id,
method: 'GET'
})
.success(successCallback)
.error(errroCallback);
} else {
alert("There was an error while passing the ID. Please refresh the page and try again");
}
}
return factory;
});
and then:
productApp.controller('ModalInstanceCtrl', function ($scope, $modalInstance, productFactory, prodId) {
console.log("this is the prod id " + prodId);
// search product in the database
productFactory.getProductById(prodId, function successCallback(data) {
$scope.prod = data;
}, function errorCallback(data, status) {
alert("An error occurred retrieving product. Please refresh the page & try again.");
});
console.log($scope.prod);
$scope.ok = function () {
console.log($scope.prodData);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
By doing it this way instead, you have access to the scope in the controller & can do whatever you need to with the returned data.
Here's what I do. I'm using $resournce instead of $http, but it should be enough to get you going. You may even want to use the $resource since it has the built in fns.
My factory:
.factory('WorkOrder', function($resource){
// $resource Usage: $resource(url[, paramDefaults][, actions]);
return $resource('/controller/get/:id.json', {}, {
/*
* By default, the following actions are returned; modify or add as needed
* { 'get': {method:'GET'},
* 'save': {method:'POST'},
* 'query': {method:'GET', isArray:true},
* 'delete': {method:'DELETE'} };
*/
});
})
My controller:
// get the work order data using the work order id from the tag attribute
var getWO = function() {
WorkOrder.get({woId:$attrs.id},
// success callback
function(response) {
// Assign the work order data to the scope
$scope.WorkOrder = response.WorkOrder;
},
// fail callback
function(response) {
// whatever...
}
);
};
getWO();
I put my success and fail fns in my controller because that's where I most likely know how I want to respond to success or failed calls. I also assign the function to a variable and then call it right after in case I want to include the fn call inside a $timeout or call it elsewhere.
Hope this answers your question.