5

For some reason my link function inside my directive is not being called. I can see that my directive is called with a console.log but not the link function. Also don't mind the controller parameter I will be using that with my parent directive. I have also tried restrict: 'E' with no luck as well. I am not using it for this example. Not sure what is causing it to skip link. Any thoughts?

module FormTest {
    angular
        .module('FormTest') //Gets the FormTest Module
        .directive('jiTab', function () {
            console.log('directive was hit');
            function linkFn(scope, ele, attrs, controller) {
                console.log('Link is called');
            };
            return {
                require: '^ji-Tabset',
                restrict: 'C',
                transclude: true,
                link: linkFn
            }
        });
 }

HTML

<ji-form name="Main Form">  
    <ji-tabset name="Tabs">  
        <ji-tab tab-name="General"></ji-tab>  
        <ji-tab tab-name="Stats"></ji-tab>  
    </ji-tabset>  
</ji-form>

Parent directive

module FormTest {
    angular
        .module('FormTest') //Gets the FormTest Module
        .directive('jiTabset', function () {
            return {
                restrict: 'E',
                transclude: true,
                replace: true,
                templateUrl: 'FormTest/views/ji-Tabset.html',
                controller: function ($scope) {
                    var tabPanelItems = $scope.tabPanelItems = [];
                    $scope.tabSettings = {
                        dataSource: tabPanelItems
                    }
                }
            };
        });
}
11
  • have link function as var linkFn while declaring. have you tried this thing? Commented Aug 26, 2015 at 14:12
  • function var linkFn? or link: var linkFn? Commented Aug 26, 2015 at 14:13
  • like this var linkFn = function (scope, ele, attrs, controller) { console.log('Link is called'); }; Commented Aug 26, 2015 at 14:16
  • My mistake, as soon as I typed that last reply I realized what you meant. I went ahead and tried that but still not seeing anything in console. Commented Aug 26, 2015 at 14:20
  • Can you post the markup where you're using this directive? Commented Aug 26, 2015 at 14:20

4 Answers 4

4
module FormTest {
    angular
        .module('FormTest') //Gets the FormTest Module
        .directive('jiTab', function () {
            console.log('directive was hit');
            function linkFn(scope, ele, attrs, controller) {
                console.log('Link is called');
            };
            return {
                require: '^ji-Tabset', //<-- this must be `^jiTabset` read mistake 1
                restrict: 'C', //<-- this must be `E` which stands for element, (jiTab) C is for class, read mistake 2
                transclude: true,
                link: linkFn
            }
        });
 }

From docs

Mistake 1

Normalization Angular normalizes an element's tag and attribute name to determine which elements match which directives. We typically refer to directives by their case-sensitive camelCase normalized name (e.g. ngModel). However, since HTML is case-insensitive, we refer to directives in the DOM by lower-case forms, typically using dash-delimited attributes on DOM elements (e.g. ng-model).

The normalization process is as follows:

  • Strip x- and data- from the front of the element/attributes.
  • Convert the :, -, or _-delimited name to camelCase.

Mistake 2

The restrict option is typically set to:

  • 'A' - only matches attribute name
  • 'E' - only matches element name
  • 'C' - only matches class name These restrictions can all be combined as needed:

'AEC' - matches either attribute or element or class name

Mistake 3

You dont have ng-transclude attribute in your jiTabset directive, make sure you have it there 'FormTest/views/ji-Tabset.html'

Worknig demo

Open browser console

angular.module('FormTest', []);
angular.module('FormTest') //Gets the FormTest Module
        .directive('jiTabset', function () {
            return {
                restrict: 'E',
                transclude: true,
                replace: true,
                template: '<div>ji-tabset<div ng-transclude></div></div>',
                controller: function ($scope) {
                    var tabPanelItems = $scope.tabPanelItems = [];
                    $scope.tabSettings = {
                        dataSource: tabPanelItems
                    }
                }
            };
        });
angular.module('FormTest') //Gets the FormTest Module
        .directive('jiTab', function () {
            function linkFn(scope, ele, attrs, controller) {
                console.log('Link is called');
            };
            return {
                require: '^jiTabset',
                restrict: 'E',
                transclude: true,
                link: linkFn
            }
        });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<div ng-app="FormTest">
  <ji-form name="Main Form">  
    <ji-tabset name="Tabs">  
        <ji-tab tab-name="General"></ji-tab>  
        <ji-tab tab-name="Stats"></ji-tab>  
    </ji-tabset>  
</ji-form>
</div>

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

2 Comments

Good catch on mistake 1! Mistake 2 I did have set to 'E' but changed to 'C' because someone in this post thought I should try it. I have changed it back to 'E' for since I am only using Element. Now for results.....I am still just hitting my directive and not my link function. I am guessing there is a Mistake 3 and 4 somewhere along the way :P
Thank you that fixed it!
1

By assigning a variable to a function and calling it where ever you want by its variable name,

angular
.module('FormTest') //Gets the FormTest Module
.directive('jiTab', function () {
 var linkFn = function (scope, ele, attrs, controller) {
    console.log('Link is called');
};
return {
    restrict: 'C',
    transclude: true,
    link: linkFn
}
});

by this way i think you can achieve i hope.

2 Comments

var linkFn = function() === function linkFn()
In Javascript var linkFn = function() and function linkFn() do the same thing.
1

Is it possible that the link function must live outside the directive ITSELF?

Try this:

       module FormTest {

       angular
       .module('FormTest') //Gets the FormTest Module
       .directive('jiTab', function () {
           console.log('directive was hit');
           return {
               require: '^jiTabset',
               restrict: 'E',
               transclude: true,
               link: linkFn
           }
       });

       function linkFn(scope, ele, attrs, controller) {
           console.log('Link is called');
       };
     }

9 Comments

This should work because of javascript hoisting. adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
Yes, but there is no need to polute the global scope
You are right, but OP is not asking about global scopes here. I think best practices state modules should be sorrounded with (function () { .... }) I will edit the answer. This is mainly for minification purposes - if I recall. Let's focus on the question.
None the less, it was worth a shot, however I am still not getting "Link is called" in the directive. But I do agree with swordf1zh that we shouldn't have to polute the global scope by doing this. I have seen plenty of cases where link works just fine being defined inside the directive
@SimchaKhabinsky I just tried you edited answer. And not only did it not work, but I am not hitting this directive anymore.
|
1
  1. You are using the directive as an element so you must change the restrict property value to 'E'.
  2. There is no controller in jiTabSet directive so there is no need to require this directive in the jiTab directive. More info: https://docs.angularjs.org/guide/directive#creating-directives-that-communicate

When a directive uses this option (require), $compile will throw an error unless the specified controller is found. The ^ prefix means that this directive searches for the controller on its parents (without the ^ prefix, the directive would look for the controller on just its own element).

Update your directive like this:

.directive('jiTab', function () {
    console.log('directive was hit');
    function linkFn(scope, ele, attrs) {
        console.log('Link is called');
    };
    return {
        restrict: 'E',
        transclude: true,
        link: linkFn
    }
});

6 Comments

I agree. That is how I had it originally. I went back and changed it (literally copy and pasted your example) and the only thing in console is: "directive was hit"
but there is a controller on ji-tabset directive... and when I use $compile with post-link instead of $link the controller is found and I get a console output. I don't get it. What my understanding was is that $link can replace post-link
Yes you are right. When I remove the transclude: true of the parent directive it works for me, but not sure why yet.
are you getting the link function's console log to appear?
|

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.