PaReeOhNos
PaReeOhNos

Reputation: 4428

Angularjs directive attributes properties all undefined

I've created a directive with the following definition

LastMeet.directive("progressBar", function() {
  return {
    restrict: "A",
    scope: {
      meeting: "&meeting"
    },
    link: function(scope, elm, attrs) {

      var meeting = scope.meeting();

      // Gather the details we need about this meeting
      var startDate = scope.meeting().start_datetime;
      var deadline  = scope.meeting().deadline;
      var complete  = scope.meeting().percentage_complete;
      console.log(meeting);
      console.log(meeting["start_datetime"]);

      // No point doing anything if we're already at 100%      
      if (complete < 100.0) {
        // Calculate how much to increment by every second
        var diff      = deadline - startDate;
        var increment = diff / 60.0;

        var timer;

        scope.percentage = complete;

        scope.onTimeout = function() {

          if (scope.percentage < 100.0) { 
            scope.percentage += increment;
            elm.css({ right: 100 - percentage + "%" });
            timer = $timeout(scope.onTimeout, 1000);
          }

        }

        // Setup our timer and get going :)
        timer = $timeout(scope.onTimeout, 1000);
      }

    }
  }
})

The meeting attribute is an object with a number of different properties. As you can see, I've added 2 console outputs, one for the meeting itself, and one for one of the properties I'm trying to access. My console has the following output

b {$resolved: false, $then: function, $get: function, $save: function, $query: function…}
   $resolved: true
   $then: function (callback, errback) {
   agenda_items: Array[2]
   deadline: 1365897600
   description: "Meeting to discuss the progress of LastMeet"
   faye_token: "7468585e529849ca992efbd3b9de6337"
   icon: null
   id: 20
   name: "LastMeet"
   percentage_complete: 100
   start_datetime: 1365897600
   __proto__: b

This is the output of the meeting object, which clearly shows the start_datetime property contained. The second console output however is simply

undefined

Why is it that the meeting object is there, and I can see everything, but when I try and access the contained properties, I just get undefined every time?

Upvotes: 1

Views: 3346

Answers (1)

PaReeOhNos
PaReeOhNos

Reputation: 4428

SUCCESS! So it appears to be an issue with the variable not being fully ready when the directive runs. The meeting object that it was looking at is created via a resource which creates a placeholder object whilst it gets the server data, and then populates the object.

My guess, is angular saw that the object existed (actually the placeholder) but the values I wanted weren't actually there yet. Not sure why the console output showed them as being there but oh well. To fix it, I added a watch statement to the object which is removed when it actually changes and gets populated. My directive now looks like this

LastMeet.directive("progressBar", function($timeout) {
  return {
    restrict: "A",
    scope: {
      meeting: "=meeting"
    },
    link: function(scope, elm, attrs) {

      unwatch = scope.$watch('meeting', function(meeting) {
        if (meeting) {
          // Gather the details we need about this meeting
          var startDate = meeting.start_datetime;
          var deadline  = meeting.deadline;
          var complete  = meeting.percentage_complete;

          // No point doing anything if we're already at 100%      
          if (complete < 100.0) {
            // Calculate how much to increment by every second
            var diff      = deadline - startDate;
            var increment = diff / 60.0;

            var timer;

            scope.percentage = complete;

            scope.onTimeout = function() {

              if (scope.percentage < 100.0) { 
                scope.percentage += increment;
                elm.css({ right: 100 - scope.percentage + "%" });
                timer = $timeout(scope.onTimeout, 1000);
              }

            }

            // Setup our timer and get going :)
            timer = $timeout(scope.onTimeout, 1000);
          }

          unwatch();
        } 
      }, true)
    }
  }
})

Now I have a few calculation issues but it's working :)

Upvotes: 2

Related Questions