Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 338
Dave Avatar asked Dec 18 '14 23:12

Dave


2 Answers

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
        });
      }
    }
  };
});
like image 179
user2943490 Avatar answered Sep 21 '22 23:09

user2943490


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

like image 23
jdmcnair Avatar answered Sep 20 '22 23:09

jdmcnair