Cannot read json response properties in angular.js controller - javascript

I am using Angular.js controller named 'forecastController'.
Angular.js Controller code is:
weatherApp.controller('forecastController',
['$scope','$routeParams','cityService', 'weatherService', function($scope, $routeParams , cityService, weatherService)
{
$scope.city=cityService.city;
$scope.days=$routeParams.days || '2' ;
$scope.weatherResult=weatherService.GetWeather($scope.city, $scope.days); //I get valid json response, the format is mentioned down below.
console.log($scope.weatherResult.city.name); //Not working, this is the problem
}]);
Json object '$scope.weatherResult' is:
{
"city":
{
"id": 2643743,
"name": "London",
"coord": {
"lon": -0.12574,
"lat": 51.50853
},
"country": "GB",
"population": 0
},
"cod": "200"
}
My service is
weatherApp.service('weatherService', ['$resource',function($resource){
this.GetWeather=function(city, days){
var weatherAPI=$resource("http://api.openweathermap.org/data/2.5/forecast/daily?APPID={{MY_API_KEY_GOES_HERE}}",{
callback:"JSON_CALLBACK"}, {get:{method:"JSONP"}});
return weatherAPI.get({q:city, cnt:days});
};
}]);
My 'forecastController' receives valid $scope.weatherResult. And in the HTML view I can access weatherResult json object properties. I have ensured it properly. For an example, {{weatherResult.city.name}} works. But, if I try to print in console.log inside my 'forecaseController' I get value undefined. The json data I am getting is from http://openweathermap.org/api
The error I get is:
TypeError: Cannot read property 'name' of undefined
at new <anonymous> (http://127.0.0.1:50926/controllers.js:19:42)
at e (https://code.angularjs.org/1.3.0-rc.2/angular.min.js:36:215)
at Object.instantiate (https://code.angularjs.org/1.3.0-rc.2/angular.min.js:36:344)
at https://code.angularjs.org/1.3.0-rc.2/angular.min.js:72:460
at link (https://code.angularjs.org/1.3.0-rc.2/angular-route.min.js:7:268)
at Fc (https://code.angularjs.org/1.3.0-rc.2/angular.min.js:68:47)
at K (https://code.angularjs.org/1.3.0-rc.2/angular.min.js:57:259)
at g (https://code.angularjs.org/1.3.0-rc.2/angular.min.js:49:491)
at https://code.angularjs.org/1.3.0-rc.2/angular.min.js:49:99
at https://code.angularjs.org/1.3.0-rc.2/angular.min.js:50:474 <div ng-view="" class="ng-scope">

Your service weatherService.GetWeather likely returns a promise. Until that promise is resolved, the properties in your $scope.weatherResult object will be undefined. Use the promise then method:
$scope.weatherResult = weatherService.GetWeather($scope.city, $scope.days);
$scope.weatherResult.$promise.then(function() {
console.log($scope.weatherResult.city.name);
});
Update: As per my comment, the service is returning a $resource object. This object has a $promise property.
Link To Codepen

Related

Vanilla Javascript filter function works perfect in one line, but not work at all for other

I am trying to filter JSON file with plain JavaScript.
city = await cities.filter(ea => {
return ea.city.toLowerCase().includes(searcher.value.toLowerCase()); //example value Belgrade
});
admin = await cities.filter(eb => {
return eb.admin_name.toLowerCase().includes(searcher.value.toLowerCase()); //example value Beograd
});
While filter that goes to city variable works perfect, one that goes to admin variable, witch is Copy-Paste of first one, return error:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'toLowerCase')
and even if I remove toLowerCase function I get same error but (reading 'includes')
this is structure of JSON file:
[
{
"city": "Tokyo",
"city_ascii": "Tokyo",
"lat": 35.6839,
"lng": 139.7744,
"country": "Japan",
"iso2": "JP",
"iso3": "JPN",
"admin_name": "Tōkyō",
"capital": "primary",
"population": 39105000,
"id": 1392685764
},
]
That just means admin_name doesn't exist, or is null/undefined for at least one object of your array.
In order to support this, you could use optional chaining like this:
admin = cities.filter(eb => {
return eb.admin_name?.toLowerCase()?.includes(searcher.value.toLowerCase()); //example value Beograd
});
As a side note, awaiting a non Promise value just returns that value, so it's useless in your case.

Ignore Hyphen in Javascript (Postman)

Building a RestAPI with Postman.
I have some JSON data:
{
"progress-update": {
"#type": "parallel-progress",
"job": {
"#href": "/api/space/job-management/jobs/4691268"
},
"taskId": 4691268,
"jobName": "Compare Config-4691268",
"state": "DONE",
"status": "SUCCESS",
"percentage": 100,
"data": "<![CDATA[Total requests: 3<br>InSync count : 3<br>OutOfSync count : 0<br>]]>",
"subTask": [
{
I want to pull the "state" value into an environment Variable that i can then use to determine wether to continue on to the next request or wait until the state is DONE.
The problem i'm running into is "progress-update": has a hyphen in it, causing my script to not recognize it.
var jsonData = JSON.parse(responseBody);
pm.environment.set("JobStatus", jsonData.progress-update.state);
Postman returns the following error:
There was an error in evaluating the test script: ReferenceError:
update is not defined
You should be able to access your JSON data with
var jsonData = JSON.parse(responseBody);
pm.environment.set("JobStatus", jsonData['progress-update'].state);
using the object bracket notation

$resource : expected response to contain an object but got an array

I know this question already exists on SO (as here : Error in resource configuration. Expected response to contain an object but got an array ) and even if I've already faced this error a few days ago, I didn't find why I'm getting it now.
On the one hand, I have a RESTful API in Node Express. It gives me access to a database, where I'm trying to get some data. When using a specific $resourcerequest, I'm getting this JSON (tested with Postman) :
[
{
"ref": 2,
"type": "string here",
"matriculeMD": 4567,
"name": "William",
"date": "2016-09-14T22:00:00.000Z",
"client": 1
},
{
"ref": 4,
"type": "string here",
"matriculeMD": 1589,
"name": "Averell",
"date": "0000-00-00",
"client": 1
}
]
On the other hand, I have an Angular JS app. This one use a factory to get the data from the API :
.factory('Things', ['$resource', function($resource) {
return $resource(
'api_url/:client_id',
{client_id: '#client_id'}, // getting some data from an ID
{'query' : {
method : 'GET', // ofc, it's a get request in the API
isArray : false // to be sure to get an object and not an array
}
}
I also have a controller which uses this factory, trying to execute the query with the param :
app.controller('ctrl', ['$scope','Things', function ($scope,$things)
{
$scope.thing = $things.query({},{'client_id':'1'});
// replacing '#client_id' from factory with 1. I also tried with quoteless 1.
}
]);
And, finally, I have an html view, where I try to use the data I'm supposed to get in $scope.thing with some <div ng-repeat'thing in things'>{{thing.ref}}</div>.
By reading other posts, I was sure that adding an isArray : false to the factory would fix the problem, as it has already fixed it in another factory.
Any idea ?
Edit : Thanks for your replies. I changed my factory code with :
.factory('Things', ['$resource', function($resource) {
return $resource(
'api_url/:client_id',
{client_id: '#client_id'}, // getting some data from an ID
{'query' : {
method : 'GET', // ofc, it's a get request in the API
isArray : true //
}
}
And it fixed the error. Now, I'm working on another problem with my $scope content which is undefined and send $promise : Promise, $resolved : Resolved. I read $resource doc to understand what it means, but I still have no idea of how to make it work.
As doldt said before, you are actually expecting an array.
Your response is an array of objects.
Either you change isArray to true or you change the response on the server to return an object.
Once you have this changed, you can use your resource on the controller this way (providing a callback for the $resource, since you are now dealing with promises) :
$things.query( {}, { 'client_id' : '1' }, function( response ){
$scope.thing = response;
});
I think you are doing wrong with isArray flag. It must be true if you are sending array.
Try it....
// Code goes here
var myApp = angular.module('myApp', ['ngResource']);
myApp.factory('Things', ['$resource',
function($resource) {
return $resource(
'data/sample.json'
//, {
// client_id: '#client_id'
//}, // getting some data from an ID
//{
// 'query': {
// method: 'GET', // ofc, it's a get request in the API
// isArray: true // to be sure to get an object and not an array
// }
//})
)
}
]);
myApp.controller('myCtrl', function($scope, Things) {
Things.query({}, {
'client_id': '1'
}).$promise.then(function(data) {
$scope.thing = data;
console.log($scope.thing);
})
});
[
{
"ref": 2,
"type": "string here",
"matriculeMD": 4567,
"name": "William",
"date": "2016-09-14T22:00:00.000Z",
"client": 1
},
{
"ref": 4,
"type": "string here",
"matriculeMD": 1589,
"name": "Averell",
"date": "0000-00-00",
"client": 1
}
]
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="angular.js#*" data-semver="2.0.0-alpha.26" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-resource.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="myCtrl">
<h1>{{1/2}}</h1>
<ul ng-repeat="t in thing">
<li>{{t.name}}</li>
</ul>
</body>
</html>
--output
0.5
William
Averell
Try:
$things.query({},{'client_id':'1'}).$promise.then(function(result){
$scope.thing = result;
console.log($scope.thing);
});

Getting data from Json string into javascript (jQuery)

I have a asp.net webservice, which is pulling some data from my database, and outputting this JSON string:
{
"NumberOfCustomers": 15,
"Customer": [
{
"CusID": "1",
"FirstName": "Ina",
"LastName": "Williamson"
},
{
"CusID": "2",
"FirstName": "Hyacinth",
"LastName": "Brady"
},
{
"CusID": "3",
"FirstName": "Coby",
"LastName": "Shannon"
}
]
}
I then try to use jQuery to display each of the customers, but i can't get it working. The purpose for this, is to use the data as a suggestion to a search field, that updates for each character written.
function FinalTest() {
$.ajax({
type: "POST",
url: "http://localhost:12724/VetWebservice.asmx/GetCustomer",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
glb = data; //variable for inspecting in Chrome
$("#testdiv3").html(data.d.NumberOfCustomers);
$.each(data.d.Customer, function () {
$("#testdiv3").append(this.CusID + ", ");
});
}
});
};
Giving me this error:
TypeError: a is undefined
jquery.min.js (linje 2)
It has something to do with the pointing to specific parts of the JSON array. But i can't figure out why it isnt working.
The "d" of the data.d path, is because asp.net webservice for some unknown reason wraps it in a d key property.
data.d.NumberOfCustomers
Its also possible to change the JSON string that i create from my webservice, if that would help solving it somehow. But my JSON syntax validates on jsonlint.com
Any help or suggestions will be highly appreciated.
EDIT: added glb object for inspecting + the result of it from Chrome
Inspecting the "glb" gives this result:
Object {d: "{"NumberOfCustomers":15, "Customer":[{"CusID":"1",…D":"15","FirstName":"Adele","LastName":"Woods"}]}"}
Which looks like what i expect; wrapped in the "d" property cause of the asp.net webservice.
When running my jquery snippet in Chrome, im also getting this error:
Uncaught TypeError: Cannot read property 'length' of undefined jquery.min.js:2
n.extend.each jquery.min.js:2
FinalTest.$.ajax.success Customers.aspx:226
j jquery.min.js:2
k.fireWith jquery.min.js:2
x jquery.min.js:4
b jquery.min.js:4
You should be using
data.NumberOfCustomers
instead of
data.d.NumberOfCustomers
and
data.Customer
instead of
data.d.Customer
.
i've tried the following code in the chrome console and it worked:
data = {
"NumberOfCustomers": 15,
"Customer": [
{
"CusID": "1",
"FirstName": "Ina",
"LastName": "Williamson"
},
{
"CusID": "2",
"FirstName": "Hyacinth",
"LastName": "Brady"
},
{
"CusID": "3",
"FirstName": "Coby",
"LastName": "Shannon"
}
]}
$.each(data.Customer,function() { alert(this.CusID); });
I remember asp.net webmethod put the result in property d but perhaps its structure a bit different then what you expect.
I would suggest to add an assignment to global var the value returned from service and investigate it using the console.
in the ajax success add line at the head of the function as follows:
glb = data; //glb will be a global scope var which you can investigate on console upon end of execution.
than on chrome console just type glb and press enter. then you would be able to investigate the object and try the each function without doing the ajax call.

Parsing JSON file with AngualrJS

I'm learning AngularJS and running some tests, but I'm having the following problem: I'm trying to read a JSON file, parse it into an object and show its properties on the screen. I read that $http parse the JSON text automatically, so I wrote the following code:
$http.get("/people").success(
function(data, status, headers, config) {
$scope.data = data.people;
}
);
This is my JSON file:
{ "people": [
{
"id": "0",
"name": "Cave Jhonson",
"company": "Aperture Science"
},
{
"id": "1",
"name": "Gustavo Fring",
"company": "Los Pollos Hermanos"
}
]
}
Which is in my project folder. I'm running a Python server. Finally, I'm trying to show the information with a simple HTML:
<p>{{data.people[0].name}}</p>
But when I open the page in Firefox the information doesn't show up and I get this error message: " Error: JSON.parse: expected property name or '}' "
My JSON is valid, so I can't understand why $http is not parsing it.
this line is inccorrect: <p>{{data.people[0].name}}</p>
You already put the code on scope in data so use that
<p>{{data[0].name}}</p>
Or you can use ng-repeat to show all the records like this
<div ng-repeat='item in data'>
<p>Id: {{item.id}}, Name: {{item.name}}, company: {{item.company}}</p>
<div>

Categories