Adrian
Adrian

Reputation: 2012

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"
}

Upvotes: 3

Views: 1267

Answers (2)

Joao Leal
Joao Leal

Reputation: 5542

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);
  });
});

Upvotes: 3

Noah Solomon
Noah Solomon

Reputation: 1261

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);
            });
        });

    }
}

Upvotes: 2

Related Questions