0
// Movements Controller
app.controller("MovementsCtrl", ["$scope", "$rootScope", "$filter", "$timeout", "$route", function($scope, $rootScope, $filter, $timeout, $route) {
  $rootScope.pageName = "Movements";

  var date = new Date();
  var currentDate = $filter('date')(new Date(), 'MM/dd/yyyy');

  $scope.labels = [];
  $scope.data = [];
  $scope.recordsArray = []; // Converts records object into an array.
  console.log($scope.recordsArray);

  firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      $rootScope.userID = user.uid;

      // Run query to pull user records.
      $timeout(function() {
        var userID = $rootScope.userID;
        var query = firebase.database().ref('/users/' + userID +'/movements/').orderByChild('created');

        query.on("value", function(snapshot) {
            $scope.records = snapshot.val();

              angular.forEach($scope.records, function(element) {
                $scope.recordsArray.push(element);
                $scope.labels.push(element.name);
                $scope.data.push(element.weight);
              });
        });
      });
    } else {
      console.log("not signed in");
    }
  });

  $scope.addRecord = function() {
    console.log("Pushed");
    var recordID = database.ref().push().key;
    var userID = $rootScope.userID;

    database.ref('users/' + userID + '/movements/' + recordID).set({
      user: userID,
      name: "Front Squat",
      sets: 5,
      reps: 5,
      weight: 350,
      created: currentDate
    });
    $route.reload();
  }
}]);

For some reason my page loads before the arrays in my JS load, rendering an empty page. I've tried wrapping everything in an init() function and loading that, but still the same issue. Can anyone help me figure out how to pre-load my JS arrays beforehand or is there another solution?

Thanks.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Joe Berthelot
  • 725
  • 4
  • 16
  • 33
  • 1
    Your arrays are populated by an asynchronous request; one thing you can do is put an ng-if on your template and only load once there is data in one or all of your arrays. Also since you are using ng-route you can put a resolve in your route definition so the page will only render after the promise is resolved. – Ronald91 Mar 20 '17 at 19:04
  • how can you be sure that the JS are loading and the API calls are running properly – Modar Na Mar 20 '17 at 19:28
  • @ModarNa because if I go from one page to another, everything loads properly. But if I am on this page and refresh, nothing loads. – Joe Berthelot Mar 20 '17 at 19:29
  • any console errors – Modar Na Mar 20 '17 at 19:30
  • @ModarNa no errors – Joe Berthelot Mar 20 '17 at 19:37
  • if you put an `alert()` after fetching the data does it fire – Modar Na Mar 20 '17 at 19:39
  • @ModarNa yes it does – Joe Berthelot Mar 20 '17 at 19:43
  • this means that controller is functioning properly ,, i`m guessing that your problem is with the data structrure returned from api or something similliar ,, try debugging like putting `alert(query)` , `alert(element)` , putting the entire {{records}} in html or other – Modar Na Mar 20 '17 at 19:49

1 Answers1

1

some reason my page loads before the arrays

The functions provided as arguments to the Firebase methods are held by the Firebase API until data arrives from the server. Those functions are executed asynchronously. This means they are executed after the enclosing functions complete.

Changes to scope that occur asynchronously outside the AngularJS framework and its digest cycle will not trigger changes to the DOM. One technique to bring events into the AngularJS framework is to convert the ES6 promises to $q service promises:

  firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      $rootScope.userID = user.uid;

      // Run query to pull user records.
      //$timeout(function() {
        var userID = $rootScope.userID;
        var query = firebase.database().ref('/users/' + userID +'/movements/').orderByChild('created');

        //USE $q.when 
        $q.when(query.once("value")).then(function(value) {
            $scope.records = value;

              angular.forEach($scope.records, function(element) {
                $scope.recordsArray.push(element);
                $scope.labels.push(element.name);
                $scope.data.push(element.weight);
              });
        });
      //});
    } else {
      console.log("not signed in");
    }
  });

Use $q Service promises that are properly integrated with the AngularJS framework and its digest cycle.

$q.when

Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted.

-- AngularJS $q Service API Reference - $q.when

georgeawg
  • 48,608
  • 13
  • 72
  • 95