Question

I have a controller that makes an xhr request to retrieve some data..

$scope.mbProductImages = [];

$http.get('product.json').success(function(data) {
    $scope.productDetails = data;
        
    $scope.mbProductImages = $scope['productDetails']['product_images'];
    console.log($scope.mbProductImages);

        for(key in $scope.mbProductImages){
            if ($scope.mbProductImages[key].current == true) {
                $scope.currentImage = $scope.mbProductImages[key]['img_lg'];
            }
        }  
});

What I really need is for a directive to retrieve data from $scope.productDetails (via attribute values) loaded in the controller and I need this code in the controller or link function of the directive instead of the $parent controller...

    $scope.mbProductImages = $scope[$attrs.content][$attrs.object];
    console.log($scope.mbProductImages);

        for(key in $scope.mbProductImages){
            if ($scope.mbProductImages[key].current == true) {
                $scope.currentImage = $scope.mbProductImages[key]['img_lg'];
            }
        }

where $scope[$attrs.content][$attrs.object]; in the directive is equivalent to $scope.productDetails from controller...

So my controller should have only this in it:

    $http.get('product.json').success(function(data) {
        $scope.productDetails = data;
    }

and my directive's controller would have the other code.

PROBLEM

My plunker: http://plnkr.co/edit/xErYnlj04P5LQsMedVWi?p=preview

What happens is,, the parent controller xhr request which fetches the data takes longer than it takes the directive to load so I get left with $scope.mbProductImages undefined

How can I make the directive wait for data from controller to load OR check for when it loaded from the directive and then apply the value?

Update

With great help from @Chandermani I have been able to see my error and come to a great solution.

Controller:

app.controller('MainCtrl', function($scope, $http) {
  $http.get('mydata.json').success(function(data) {
    $scope.productDetails = data;
    console.log($scope.productDetails);
  });

});

Directive:

app.directive("myImages", function() {
return {
restrict: "E",
scope: true,
templateUrl: "template.html",
compile: function(element, attrs) {
  return function(scope, element, attrs) {
    scope.myContent = attrs.content;
    scope.myObject = attrs.object;
    scope.$watch(scope.myContent,function(newValue,oldValue){
      if(newValue) {
        scope.mbProductImages = newValue[scope.myObject];
        console.log(scope.mbProductImages);
        for(key in scope.mbProductImages){
         if (scope.mbProductImages[key].current == true) {
            scope.currentImage = scope.mbProductImages[key]['img_lg'];
         }
        } 
      }
    })
  }; // return

} // compile
}
});
Was it helpful?

Solution

You don't make directive to wait, but watch of changes to a scope variable using scope.$watch.

Your watch expression should point to the property that you want to watch. Something like

$scope.$watch($attrs.content + $attrs.object, function(newValue,oldValue) {
   if(newValue) {
          //your logic here
   }
});

The first parameter of watch should be path to the property of the object you want to watch.

Update: I have tried to fix your plunkr see if helps http://plnkr.co/edit/fKJ2nZcytKubC9JjiaTS?p=preview I have basically put a watch on productDetails property.

OTHER TIPS

If you don't want to use $watch you can use ng-model to pass data into your directive. In this case your directive could look like this:

app.directive('myDirective',function(){
        restrict: 'E',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel){

        //called when controller change ngModel value
        ngModel.$render = function(){
            console.log('ngModel has changed');

            //reading data from ngModel         
            scope.currentModelValue = ngModel.$modelValue;  
            processData()               
        }           

        function processData(){
            //process your data
            scope.currentModelValue = "new value";
            updateModel();
        }

        function updateModel(){
            //updating data
            ngModel.$setViewValue(scope.currentModelValue)
        }
    }
});

HTML:

<my-directive ng-model="yourData"></my-directive>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top