简体   繁体   中英

Can't access variable inside angular.js controller

This is my controller:

app.controller("PlaceController", ['$http', function($http){

    this.places = shops;
    var hotels = this;
    hotels.objects = [];
    this.spots = new Array;

    this.newPlace = {};

    this.city = new String();

    this.addPlace = function() {
        this.places.push(this.newPlace);
        this.newPlace = {};

        var request = *some query syntax, sorry for hiding*

        $http.get(request).success(function(data) {
            hotels.objects = data;
            console.log(hotels.objects.elements);
        });

        for (each in hotels.objects.elements) {
          this.spots.push(each.tags.name);
        };

        console.log(this.spots);

}}] );

I get an empty array when I log this.spots to the console. The http request etc work perfectly because the console.log(hotels.objects.elements) statement works perfectly.

Because of this problem, I can't output it into my HTML either. What should I do?

You are issuing an asynchronous request to get the spots, but you're logging them before they complete.

Change this.addPlace to log / act on the spots array inside the promise callback:

this.addPlace = function() {
    this.places.push(this.newPlace);
    this.newPlace = {};

    var request = *some query syntax, sorry for hiding*

    $http.get(request).success(function(data) {
        hotels.objects = data;
        console.log(hotels.objects.elements);

        for (each in hotels.objects.elements) {
          this.spots.push(each.tags.name);
        };

        console.log(this.spots);
    });

You're adding to the spots array before the ajax request is done, move your calls to push inside the callback:

$http.get(request).success(function(data) {
        hotels.objects = data;
        console.log(hotels.objects.elements);
        angular.forEach(hotels.objects.elements, function(value) {
                hotels.spots.push(value.tags.name);
        });
});

Also, you should really be using $scope instead of references to this . This would simplify your code a bit, without needing to rename this to hotels

full controller code using $scope

app.controller("PlaceController", ['$scope', '$http', function($scope, $http){
    $scope.places = shops;    
    $scope.objects = [];
    $scope.spots = new Array;
    $scope.newPlace = {};
    $scope.city = new String();

    $scope.addPlace = function() {
        $scope.places.push($scope.newPlace);
        $scope.newPlace = {};

        var request = *some query syntax, sorry for hiding*

        $http.get(request).success(function(data) {
            $scope.objects = data;
            console.log($scope.objects.elements);

            angular.forEach($scope.objects.elements, function(value, key) {
                $scope.spots.push(value.tags.name);
            });
            // spots is ready, log it, do whatever
            console.log($scope.spots);
        });       
}}] );

NOTE: Using $scope means you won't need to call this from your html to reference the objects and functions defined in your controller.

An example:

<div ng-controller="PlaceController">
    <!-- no need to call places.city, if you use $scope just write city -->
    {{city}}
</div>

EDIT : You probably shouldn't use JavaScript's for-in , the problem with it is that it iterates on the names or indexes of your objects/arrays.

An example:

var someArray = ['a', 'b', 'c'];
for (i in someArray) {
   console.log(i); // prints 0, 1, 2
   console.log(someArray[i]); // prints 'a', 'b', 'c'
}

This is different from any for-in/for-each implementation in other popular languages.

Anyway, in this case I've edited the code above to use Angular's forEach , which is a more appropriate solution (many libraries implement custom for-each functions to fix JS's weird for-in ) You can read more in Angular's docs

Another option, in plain javascript is, if $scope.objects.elements is an array, using the map() function , like this:

$scope.spots = $scope.objects.elements.map(function(value) {
    return value.tags.name; // value is an item in object.elements
});

try this ..

due to your async call you need to perform task inside success

$http.get(request).success(function(data) {
        hotels.objects = data;
        console.log(hotels.objects.elements);

         for (each in hotels.objects.elements) {
              hotels.spots.push(each.tags.name);
          };

        console.log(this.spots);
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM