7

I'm building Angular/Express app, I load data with controller and try to work with data in a function but I get error in console

Cannot read property 'toLowerCase' of undefined

When I manually write JSON data it works just fine. Anyone had this error and why is it happening?

Edit: Also I want function to work on click, when I want it not when it's loaded, also I use data from listData in view so I know it's loaded

Controller

var self = this; 
self.listData = [];

var self = this; 
self.listData = [];

$http.get('/myList')
.success(function (data) {
    self.listData = data;
    console.log(data);
})
.error(function (data) {
    console.log('Error: ' + data);
});

self.myFunc = function(){
    var map = self.listData.reduce(function (p, c) {
        p.set(c.name.toLowerCase(), c.surname);
        return p;
    }, new Map());

    console.log(...map);
}
Cœur
  • 37,241
  • 25
  • 195
  • 267

4 Answers4

1

HTTP.GET is an asynchronous function

You could call your function which turns the data to lowercase in the .success of your http.get. That way you know that the data has arrived. Now you might be executing this function a bit too early which means that you do not yet have the data in your list.

If you try to run the toLowerCase() on your data, before you actually retrieved the data you will get this error. That is one of the things you learn to deal with when working with web requests.

For example writing your code like this would work.

   $http.get('/myList')
           .success(function (data) {
                self.listData = data;
                myFunc(listData);
                console.log(data);
           })
           .error(function (data) {
                console.log('Error: ' + data);
           });

 }

 function myFunc(){

    var map = self.listData.reduce(function (p, c) {
                p.set(c.name.toLowerCase(), c.surname);
                return p;
           }, new Map());

           console.log(...map);

 }
Dylan Meeus
  • 5,696
  • 2
  • 30
  • 49
  • 2
    This function is executed on click, so the view has loaded the data is loaded into view. vm.word works fine when i console it. But just wont works with function. Function should get access to it becuse when i manually write vm.json and work with him it converts no problems. – Absolute Beginer Aug 05 '16 at 09:30
  • You kept the typo in there so it will work even less. – gyc Aug 05 '16 at 09:38
  • @gyc I fixed it. I saw your answer on this post, and the OP replied that this was due to a typo in his post, so I stopped my edit and forgot that I had copy pasted that part. ;-) – Dylan Meeus Aug 05 '16 at 09:39
  • It has nothing to do http.get being asynchronous. The callback for `.reduce` won't be called on empty array. – Salman A Aug 05 '16 at 16:40
1

Here is your updated code works on click of an element:

jQuery("#a-div-to-click").on("click", function() {
    var self = this; 
    self.listData = [];
    $http.get('/myList').success(function (data) {
            self.listData = data;
            console.log(data);
            self.myFunc();
       }).error(function (data) {
            console.log('Error: ' + data);
       });
    }
    self.myFunc = function(){
        var map = self.listData.reduce(function (p, c) {
                p.set(c.name.toLowerCase(), c.surname);
                return p;
        }, new Map());

        console.log(map);
    }

});

V2) The data is loaded at "onload" phase and the process done at "onclick" phase:

app.controller('yourController', function ($scope, $http) {

    $scope.fetchData = funcion(onSuccess) {
        $http.get('/myList').success(function (data) {
                $scope.aDivlistData = data;
                console.log(data);
                if (onSuccess != null) {
                    onSuccess();
                }
           }).error(function (data) {
                console.log('Error: ' + data);
           });
        }
    }();

    $scope.onADivClicked = function() {
        if ($scope.aDivlistData == null) {
            $scope.fetchData($scope.populateMap);
        } else {
            $scope.populateMap();
        }

    };

    $scope.populateMap = function() {
        var map = $scope.aDivlistData.reduce(function (p, c) {
                p.set(c.name.toLowerCase(), c.surname);
                return p;
        }, new Map());

        console.log(map);
    }
}
//html part:
//<div id="a-div-to-click" ng-click="onADivClicked()">A Div</a>
Bahadir Tasdemir
  • 10,325
  • 4
  • 49
  • 61
0

Just by looking at your code. It looks like "c.name" is undefined. May be you can print that variable out and see what's in it

Gavy
  • 407
  • 3
  • 8
0

c.name is undefined for some item in your listData. Checkout JSON which you receive from server, not faked one.

NOTE: $http.get is asynchronous. Putting self.myFunc = ... into success handler of $http.get suppose to give correct behaviour. You can take a look on Understanding Asynchronous Code in Layman's terms to see how async works.

Good Luck ! :)

Community
  • 1
  • 1
Andriy Ivaneyko
  • 20,639
  • 6
  • 60
  • 82