1
votes

I'm pretty new to Angular and I'm using firebase as my backend. I was hoping someone could debug this issue. When I first go to my page www.mywebsite.com/#defaultHash the data doesn't load into the DOM, it does after visiting another hash link and coming back though.

My controller is like this:

/* initialize data */

var fb = new Firebase('https://asdf.firebaseio.com/');

/* set data to automatically update on change */

fb.on('value', function(snapshot) {

  var data = snapshot.val();
  $scope.propertyConfiguration = data.products;
  console.log($scope.propertyConfiguration);
  console.log("Data retrieved");

});

/* save data on button submit */

$scope.saveConfigs = function(){

  var setFBref = new Firebase('https://asdf.firebaseio.com/products');
  setFBref.update($scope.propertyConfiguration);
  console.log("configurations saved!");

};

I have 3 hash routes say "Shared", "Registration", and "Home" with otherwise.redirectTo set to "Shared".(They all use this controller) Here's the error that occurs: (all "links" are href="#hashWhereever")

1) Go to website.com/#Shared or just refresh. Console logs $scope.propertyConfiguration and "Data Retrieved". DOM shows nothing.

2) Click to website.com/#Registration, console logs $scope data properly, DOM is loaded correctly.

3) Click back to website.com/#Shared, console logs $scope data properly yet this time DOM loads correctly.

4) Refresh currently correctly loaded website.com/#Shared. DOM elements disappear.

Since $scope.data is correct in all the cases here, shouldn't Angular make sure the DOM reflects the model properly? Why is it that the DOM loads correctly only when I am clicking to the page from another link.

I can "fix" it by adding window.location.hash = "Shared" but it throws a huge amount of errors in the console.

FIXED:(sorta)

The function $scope.$apply() forces the view to sync with the model. I'd answer this question myself and close it but I'm still wondering why the view doesn't load correctly when I correctly assign a value to $scope. If Angular's "dirty checking" checks whenever there is a possibility the model has changed, doesn't assigning a value to $scope overqualify?

1

1 Answers

2
votes

Angular has no way to know you've assigned a value to $scope.variable. There's no magic here. When you run a directive (ng-click/ng-submit) or Angular internal functions, they all call $apply() and trigger a digest (a check of the dirty flags and update routine).

A possibly safer approach than $apply would be to use $timeout. Currently, if you call a write op in Firebase, it could synchronously trigger an event listener (child_added, child_changed, value, etc). This could cause you to call $apply while still within a $apply scope. If you do this, an Error is thrown. $timeout bypasses this.

See this SO Question for a bit more on the topic of digest and $timeout.

This doc in the Angular Developer Guide covers how compile works; very great background read for any serious Angular dev.

Also, you can save yourself a good deal of energy by using the official Firebase bindings for Angular, which already take all of these implementation details into account.

Vaguely Related Note: In the not-too-distant future, Angular will be able to take advantage of Object.observe magic to handle these updates.