Search code examples
angularjsdesign-patternsangularjs-directiveangularjs-scope

Deep directives design in Angular


I know isolated scope and read some resources about Angular. Now I am stuck with a problem; suppose I have very deep directives:

A wraps B wraps C wraps D wraps E
X wraps Y wraps D wraps E

A, B, C, D, E, X, Y are directives. D and E need some information of something which are passed to their isolated scopes, I call this info is info: '='. This info belongs to A or X. So if I need to use info in D and E, I have to pass it in paths: A -> B -> C -> D -> E or X -> Y -> D -> E.

That means B, C, or Y have to create their isolated scopes to hold info value. Too deep! If I in future add some directives in the middle of paths, I have to do same thing as above. I don't think it's good design.

Can anyone give me some suggestions on to resolve this design problem in Angular?


Solution

  • OK. You could:

    1 - Keep info inside a service and just inject it wherever you need.

    2 - Allow directives to communicate with each other via controller. So for example, if you want directive E to get information form directive A, A must have a controller and some kind of getter method, directive E would require this controller and use the get method inside the link function. Easier to visualize with code.

    .directive('aDir', function () {
      return {
         restrict: 'E',
         transclude: true,
         template: '<p>aDir: {{info}}<span ng-transclude></span></p>',
         scope: {
           info: '='
         },
         controller: function ($scope) {
            this.getInfo = function () {
               return $scope.info;
            };
         },
         link: function (scope, elm, attrs) {
    
         }
      };
    })
    
    .directive('eDir', function () {
      return {
         restrict: 'E',
         template: '<p>eDir: {{info}}</p>',
         require: '^aDir',
         scope: { },
         link: function (scope, elm, attrs, aDirController) {
              scope.$watch(function () {
                return aDirController.getInfo();
              }, function (newVal, oldVal) {
                  scope.info = newVal;
              });
         }
      };
    });
    

    Here is a JSBin.

    Here you have more info about directive's require attribute.