-2

I have a problem with accessing json data via a jquery-ajax request in JavaScript. I keep hitting against a 'Cannot read property [0] of undefined' error that I get in G. Chrome's console. I have tried to refer to other features than feature '0', as well as not specifying any, but I still get not results when running my script on browser and searching for one of the json Sources (going from 0001 to 0012).

This is part of my education so I have to access the data in this specific way. I'll attach my code, which relies also on jquery-1.7.1.min.js and ol.js libraries. I'll be immensely grateful to whom will have a lead on what I'm doing wrong.

<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<div class="pagewrapper">
  <div id="header"></div>
  <div id="controls">
    <h1>Controls</h1>
    <div ng-app="myApp" ng-controller="locationController">
      Enter SourceID(from 0001 to 0012):
      <input ng - model="location.Source">
      <button class="btn btn-default" ng - click="location.getElevation()">Search</button>
      <p>Elevation: {{location.ele}}</p>
    </div>
  </div>
var mainApp = angular.module("myApp", []);

mainApp.controller('locationController', function($scope) {
  $scope.location = {
    Source: ('0001'),
    getElevation: function() {
      $.ajax({
        url: 'https://services.arcgis.com/Sf0q24s0oDKgX14j/arcgis/rest/services/gpsData/FeatureServer/0/query?where=Source=' + $scope.location.Source + '&outFields=*&f=geojson',
        method: 'GET',
        success: function(response) {
          $scope.location.ele = response.features[0].properties.ele;
          $scope.$apply();
        },
        error: function() {}
      })
    }
  }
})
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
giozzz
  • 1
  • 1
  • Have you inspected the response object in the console tools to ensure it is in fact defined and it's a list? What is the returned object? – scrappedcola May 24 '21 at 14:46
  • Looks like features property does not exist in response object. Log response first thing in the success callback. Also when accessing properties like this, it is always a good practice to check if the property exists. Like in this case, check if features exist and then check for its [0](1st element). – Tushar Shahi May 24 '21 at 14:48
  • Please take care when copy+pasting code in to the question - you put the HTML in to the JS and it ruined the formatting making it very hard to read. Also note that you appear to be using jQuery and Angular together which is not a good idea. – Rory McCrossan May 24 '21 at 14:49
  • `Cannot read property [0] of undefined` means whatever you are using `[0]` on is `undefined`, not just that `[0]` doesn't exist on it. – Kevin B May 24 '21 at 14:55

1 Answers1

0

Just ran your code. As other pointed, is important to run console.log on the results to debug. On your case, added a console.log at success's function

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml: lang="en-gb" lang="en-gb">
<head>
    <meta http - equiv="content-type" content="text/html; charset=utf-8" />
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <title> Trial
    </title>
    </script>
    </script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">
    </script>
</head>
<body>
    <div class="pagewrapper">
        <div id="header">
        </div>

        <div id="controls">
            <h1> Controls
            </h1>

            <div ng-app="myApp" ng-controller="locationController">
                Enter SourceID(from 0001 to 0012):
                <input ng-model="location.Source">
                <button class="btn btn-default" ng-click="location.getElevation()"> Search</button>
                <p>Elevation: {{location.ele}}</p>
            </div>
        </div>

        <script>
            var mainApp = angular.module("myApp", []);
            mainApp.controller('locationController', function($scope) {
                $scope.location = {
                    Source: ('0001'),
                    getElevation: function() {
                        $.ajax({
                            url: 'https://services.arcgis.com/Sf0q24s0oDKgX14j/arcgis/rest/services/gpsData/FeatureServer/0/query?where=Source=' +
                                $scope.location.Source + '&outFields=*&f=geojson',
                            method: 'GET',
                            success: function(response) {
                                console.log(response)
                                $scope.location.ele = response.features[0].properties.ele;
                                $scope.$apply();
                            },
                            error: function() {}
                        })
                    }
                }
            })
        </script>
</body>
</html>

It got a response like this: Response ajax

But that is a string, not an object. Look a this log:

console.log(typeof response) // result is string

So you are trying to access a key on a string instead of a object, so you need to parse the string to an object, for example like this:

JSON.parse(response)

So it is really:

JSON.parse(response).features[0].properties.ele

That will make your code work: Working code

EDIT: To access other data, you need to define the variable of the object you need at the function, and the render on the DOM. For example, latitude:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml: lang="en-gb" lang="en-gb">

<head>
    <meta http - equiv="content-type" content="text/html; charset=utf-8" />
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <title> Trial
    </title>
    </script>
    </script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">
    </script>
</head>

<body>
    <div class="pagewrapper">
        <div id="header">
        </div>

        <div id="controls">
            <h1> Controls
            </h1>

            <div ng-app="myApp" ng-controller="locationController">
                Enter SourceID(from 0001 to 0012):
                <input ng-model="location.Source">
                <button class="btn btn-default" ng-click="location.getElevation()"> Search</button>
                <p>Elevation: {{location.ele}}</p>
                <p>Latitude: {{location.lat}}</p>
            </div>
        </div>

        <script>
            var mainApp = angular.module("myApp", []);
            mainApp.controller('locationController', function($scope) {
                $scope.location = {
                    Source: ('0001'),
                    getElevation: function() {
                        $.ajax({
                            url: 'https://services.arcgis.com/Sf0q24s0oDKgX14j/arcgis/rest/services/gpsData/FeatureServer/0/query?where=Source=' +
                                $scope.location.Source + '&outFields=*&f=geojson',
                            method: 'GET',
                            success: function(response) {
                                $scope.location.ele = JSON.parse(response).features[0].properties.ele;
                                $scope.location.lat = JSON.parse(response).features[0].geometry.coordinates[1];
                                $scope.$apply();
                            },
                            error: function() {}
                        })
                    }
                }
            })
        </script>
</body>
</html>

Will give you: With latitude

  • OMG this worked!! I'm so grateful! – giozzz May 24 '21 at 15:07
  • Glad to hear. Feel free to mark the answer as accepted if you want :) – Ignacio Acuña Frías May 24 '21 at 15:13
  • I will, but first I would like to pose another couple of questions: 1) What if I would like to access all elevation data from all features on Source '0001' , and not only feature 0? 2) What if I'd like to access coordinate data instead of elevation. I'm trying the following and it seems not to be working with the solution you provided: $scope.location.lat = JSON.parse(response).features[0].geometry.coordinates[1]; – giozzz May 24 '21 at 15:30
  • I am making a lot of guess on these answers, but here it comes 1) How I am seing your data structure, you have an array named features, which all have some "coordinates" of some point on a space. You already have all the elevation data, and you can access any of those elements by just select which one you want, for example: JSON.parse(response).features[0] or JSON.parse(response).features[1], etc... But a probably better approach is to filter by attributes, for example (https://stackoverflow.com/questions/2722159/how-to-filter-object-array-based-on-attributes) – Ignacio Acuña Frías May 24 '21 at 16:40
  • Then you could filter by id (look at the object structures of the array, they have an id): { "type":"Feature", "id":1, "geometry":{ "type":"Point", "coordinates":[ 13.3501449984066, 47.8731309865332 ] }, "properties":{ "Source":1, "ele":780.728, "time":1167987853000, "ObjectId":1 } } So you can perform filter based on atributtes given that Object's structure – Ignacio Acuña Frías May 24 '21 at 16:42
  • So, in your input, you could ask for the SourceID, and the ID of the point of the features array. 2) I made and edit to the question to answer to show you how to do it – Ignacio Acuña Frías May 24 '21 at 16:45