Leonardo
Leonardo

Reputation: 4228

Directive within another directive - scope var undefined

I'm trying to generate a smart-table directive from within a custom directive I've defined:

<div ng-controller="myContrtoller">
  <containing-directive></containing-directive>
</div>

The directive definition:

angular.module('app')
.directive('containingDirective', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<table st-table="collection" st-pipe="scopeFun"></table>', 
        link: function(scope, elem, attrs) {
            scope.scopeFun = function () {
                // solve the misteries of life
            }
        }
    }
});

As you can see my directive tries to replace the element by the template generated by the st-table directive, using the st-pipe directive depending on the first, briefly:

ng.module('smart-table')
  .controller('stTableController' function () {
      // body...
  })
  .directive('stTable', function () {
    return {
      restrict: 'A',
      controller: 'stTableController',
      link: function (scope, element, attr, ctrl) {
        // body
      }
    };
  })
  .directive('stPipe', function (config, $timeout) {
    return {
      require: 'stTable',
      scope: {
        stPipe: '='
      },
      link: {

        pre: function (scope, element, attrs, ctrl) {
          var pipePromise = null;
          if (ng.isFunction(scope.stPipe)) { // THIS IS ALWAYS UNDEFINED
            // DO THINGS
          }
        },

        post: function (scope, element, attrs, ctrl) {
          ctrl.pipe();
        }
      }
    };
  });

Problem:
The st-pipe directive checks the scope var stPipe if it is defined or not by: if (ng.isFunction(scope.stPipe)). This turns out to be ALWAYS undefined. By inspecting I found two things:

  1. From the stPipe directive, the value supposed to be scope.stPipe that is my scopeFun defined within my containingDirective is undefined on the scope object BUT defined within the scope.$parent object.
  2. If I define my $scope.scopeFun within the myContrtoller I don't have any problem, everything works.

Solution:
I did find a solutions but I don't know what really is going on:

  1. Set replace: false in the containingDirective
  2. Define the scope.scopeFun in the pre-link function of containingDirective

Questions:

  1. Why is the scopeFun available in the stPipe directive scope object if defined in the controller and why it is available in the scope.$parent if defined in the containingDirective?
  2. What is really going on with my solution, and is it possible to find a cleaner solution?

Upvotes: 1

Views: 180

Answers (1)

Leonardo
Leonardo

Reputation: 4228

From the docs: "The replacement process migrates all of the attributes / classes from the old element to the new one" so what was happening was this:

<containing-directive whatever-attribute=whatever></containing-directive>

was being replaced with

<table st-table="collection" st-pipe="scopeFun" whatever-attribute=whatever></table>

and somehow st-table did not enjoy the extra attributes (even with no attributes at all..).
By wrapping the containingDirective directive template within another div fixed the problem (I can now use replace:true):

<div><table st-table="collection" st-pipe="scopeFun"></table></div>

If someone has a more structured answer would be really appreciated

Upvotes: 0

Related Questions