简体   繁体   中英

AngularJS returning undefined on first ng-click

Im a building a system that fetches new events based on the date sent to the API using AngularJS. I am currently still in in the learning stages of AngularJS so Im wondering is there something Im missing.

My problem is , even though the data loads correctly on the page load, when I click the button the first time I am getting undefined for $scope.newEvents even though it is successfully getting the data from the API (I can see in the console).

I was attempting to build a JSFiddle but I was having trouble getting the whole thing to work on it.

here is the html output...

The output...

    <ul>
      <li ng-repeat="event in events | orderBy:'-event_date' ">
        <span >{{event.event_date}},{{event.event_name}}, {{event.event_venue}}, {{event.event_description}} </span>
      </li>
    </ul>

The get request in my js...

var eventApp = angular.module('eventApp', ['ngRoute']);


eventApp.factory("services", ['$http', function($http) {

    var apiBase = 'http://example.net/angular-api/'

    var service = {};

    service.getEvents = function(latest_date){
        return $http.get(apiBase + 'events?latest_date=' + latest_date);
    }

    return service;   
}]);

When the page loads its working fine, it makes a successful request and updates $scope.events ...

var date = new Date();

$scope.todays_date = date.getUTCFullYear() + '-' +
    ('00' + (date.getUTCMonth()+1)).slice(-2) + '-' +
    ('00' + date.getUTCDate()).slice(-2) + ' ' + 
    ('00' + date.getUTCHours()).slice(-2) + ':' + 
    ('00' + date.getUTCMinutes()).slice(-2) + ':' + 
    ('00' + date.getUTCSeconds()).slice(-2);

$scope.events = [{}];

services.getEvents($scope.todays_date).then(function(data){
    $scope.events = data.data;

});

But when click the button that loads the ng-click function I am getting undefined for my data. I initially figured there was something wrong with the date format, but the fact that it is successfully getting the data is what is confusing me. The problems start at then below...

        $scope.addFiveNew = function (new_or_old) {

        if (new_or_old == 'new') {

            $scope.latest_date = $scope.getNewestDate();


            services.getEvents($scope.latest_date).then(function(data){
                $scope.newEvents = data.data;
            });

            console.log($scope.newEvents);

            // update the list (this is currently failing on first click)
            angular.forEach($scope.newEvents,function(item) {
                $scope.events.push(item);
            });


        }

this function in the controller creates the date to send...

$scope.getNewestDate = function() {
        var sortedArray = $filter('orderBy')($scope.events, 'event_date');
        var NewestDate = sortedArray[sortedArray.length - 1].event_date;
        return NewestDate;
    };  

Here is an example of some data...

{
 "event_id":"1",
 "event_name":"Event 1",
 "event_date":"2014-09-26 00:00:00",
 "event_venue":"Limerick",
 "event_description":"stuff"
}

The bit inside the then is asynchronous, so the rest of your code can run without the scope being updated by the return of your service method, right?

services.getEvents($scope.latest_date)
.then(function(data){            //whenever the service returns
  $scope.newEvents = data.data;  //update the scope

  console.log($scope.newEvents); //log the results

  // update the list
  angular.forEach($scope.newEvents,function(item) {
     $scope.events.push(item);
  });
});

It looks to me like the getEvents call on your service is returning a promise. Calling .then on a promise will call the passed function asynchronously. So, your $scope.newEvents = data.data; will get called after the rest of the statements in that block. I think you can change your .then statement to the following and it should work:

$scope.addFiveNew = function (new_or_old) {

    if (new_or_old == 'new') {

        $scope.latest_date = $scope.getNewestDate();

        services.getEvents($scope.latest_date).then(function(data){
            $scope.newEvents = data.data;
            console.log($scope.newEvents);
            // update the list (this is currently failing on first click)
            angular.forEach($scope.newEvents,function(item) {
                $scope.events.push(item);
            });
        });

    }
}

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