4

I have two directives on the same page, but on a different element. Something like that:

<div directive-one>
    <div directive-two></div>
</div>

In directiveOne, I create some variable (let's say, $scope.pageConfig.variable). I want directiveTwo to use this variable.

The problem - directiveOne not always loads before directiveTwo.

The question is - is there a way to make sure directiveOne loads before directiveTwo, so that the variable would be available for directiveTwo?

Thanks :)

UPDATE: I've found the answer is supposed to be to use a controller in directiveOne like this:

return {
controller: function($scope){ $scope.variable = variable; },
link : ...
}

The problem is that I get an error [$injector: unpr] when using it this way. Should this solve my issue? Any idea why this creates an error for me?

4
  • 2
    You can give higher priority to directive one. Refer to docs.angularjs.org/api/ng/service/$compile - priority Commented Jul 22, 2014 at 14:39
  • Please show your directive codes. Where do you put your logic in both directives, postLink? Commented Jul 22, 2014 at 14:47
  • I put the logic in the link function. I tried using the controller, which is supposed to work, but I get an error. Now I see I get an error every time I put a controller in any of my directives. No matter what's in the controller. Odd... Commented Jul 22, 2014 at 14:53
  • If you've got an answer to your post, please create an answer and mark it as the answer. Commented May 14, 2015 at 1:49

4 Answers 4

6

How about requiring directiveA in directiveB:

var myApp = angular.module('myapp', [])
.run(function(){

});

myApp.directive('fooDirective', function() {
    return {
      restrict: 'A',
      controller: function(){
        this.pageConfig = {
          someVaraible: 'value from foo'
        };
      }
    }
  });

  myApp.directive('barDirective', function() {
    return {
      restrict: 'A',
      require: '^fooDirective',
      link: function(scope, element, attr, fooDirectiveController){
        console.log(fooDirectiveController.pageConfig);
      }
    }
  });

Here's a Plunk and more information on extending directives, and here some more info

Sign up to request clarification or add additional context in comments.

Comments

4

If you would like to run some code in the parent directive before the child, you could put your code in the preLink function. The preLink function can be specified like this:

return {
  link: {
    pre: function preLink(scope, element, attrs) {
      // put your code here
      // code in here of parent will be executed before child's (top down).
    },
    post: function postLink(scope, element, attrs) {
      // code in here of parent will be executed after child's (bottom up).
    }
  }
};

Comments

3

I've found the answer. One solution can be miron's solution. The problem is, it works for parent directives that are waiting for child directives (in regards to the DOM tree) -

You can require it on a parent DOM element, OR on the same DOM element

Another solution, which worked for me, was to use a directive's controller. This blog post explains it very well. In short, the controllers are activated in the order the dom tree is being read, while the link is being read "on the way back".

My problem was that you have to accept $scope (as in controller: function($scope) and not controller: function(scope)) for the controller to actually accept the scope. Not intuitive, but that's how it is :)

Comments

-2

You can always set a watch on the variable, if there's a change to the variable it will update.

Here's a quick example,

App.directive('myDirective', function() {
  return {
      restrict: 'AE',
      replace: 'true',
      link: function ($scope, element, attrs) 
      {
          $scope.test = "testme"
      } 
  };
});


App.directive('mySecondDirective', function() {
  return {
      restrict: 'AE',
      replace: 'true',
      link: function ($scope, element, attrs) 
      {
          $scope.$watch('test', function() {
                       alert('hey, myVar has changed!');
       });
      } 
  };
});

As an alternative, you could set a timeout in the second directive,

$scope.test = "Waiting to update";


setTimeout(function () {
    $scope.$apply(function () {
          console.log($scope.test);
    });
}, 2000);

Hopefully that will help you!

2 Comments

That's not so good. Consider the case in which dom elements are created along with the directive (like a kendoui widget) and this directive is responsible for the options creation...
The case wasn't stated in the initial question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.