Dave
Dave

Reputation: 2765

AngularJS directive loading before data

Let's say I'm loading a variable into $scope with $http:

$http.get('/teachers/4').success(function(data){
  $scope.teacher = data;
});

My template uses this data:

Teacher: {{teacher.name}}
<students-view students="teacher.students"></students-view>

This directive can load BEFORE teacher finishes loading, but my directive has code that depends on the teacher.students array being loaded:

app.directive('studentsView', function(){
  return {
    scope: { students: '=' },
    controller: function($scope){
      _.each($scope.students, function(s){
        // this is not called if teacher loads after this directive
      });
    }
  };
});

How do I get the behavior that I want here? I don't want to stop using $http, and I would like to not have to assign a promise to the scope if possible.

Upvotes: 9

Views: 15488

Answers (2)

jdmcnair
jdmcnair

Reputation: 1315

You'll probably need to do some kind of watch on students to know when it is updated, then run your _.each when the watch is triggered:

app.directive('studentsView', function(){
  return {
    scope: { students: '=' },
    controller: function($scope){
      scope.$watch('students', function(newValue, oldValue) {
        _.each($scope.students, function(s){
          // this is not called if teacher loads after this directive
        });     
      };
    }
  };
});

More on $watch: https://docs.angularjs.org/api/ng/type/$rootScope.Scope

Upvotes: 3

user2943490
user2943490

Reputation: 6940

Use a watch to wait for students to be available. Once it's available you call the code that depends on it, then remove the watch. You can skip removing the watch if you want the code to execute every time students changes.

app.directive('studentsView', function(){
  return {
    scope: { students: '=' },
    link: function($scope){
      var unwatch = $scope.$watch('students', function(newVal, oldVal){
        // or $watchCollection if students is an array
        if (newVal) {
          init();
          // remove the watcher
          unwatch();
        }
      });

      function init(){
        _.each($scope.students, function(s){
          // do stuff
        });
      }
    }
  };
});

Upvotes: 21

Related Questions