简体   繁体   中英

How to pass the angular's directive's link and controller to it

Say that I have a straight forward directive:

angular
    .module('myApp')
    .directive('myDiv', ['MyService1', 'MyService2', 
        function(MyService1, MyService2) {
            return {
                restrict: 'E',
                link: function(scope, element, attrs) {
                    scope.myVars = MyService1.generateSomeList();

                    MyService2.runSomeCommands();

                    // Do a lot more codes here
                    // Lines and Lines

                    // Now run some embedded function here
                    someEmbeddedFunction();

                    function someEmbeddedFunction()
                    {
                        // More embedding
                        // This code is really getting nasty
                    }
                }
            }
        }
    ]);

The code above has so much indentation and crowded that at least to me, it is very hard to read and unenjoyable to work with.

Instead, I want to move the link and someEmbeddedFunction out and just call them. So something along the lines of this:

function link(scope, element, attrs, MyService1, MyService2)
{
    scope.myVars = MyService1.generateSomeList();

    MyService2.runSomeCommands();

    // Do a lot more codes here
    // Lines and Lines

    // Now run some embedded function here
    someEmbeddedFunction();
}

function someEmbeddedFunction()
{
    // This is much nicer and less tabbing involved
}

angular
    .module('myApp')
    .directive('myDiv', ['MyService1', 'MyService2', 
        function(MyService1, MyService2) {
            return {
                restrict: 'E',
                link: link          // This is line that I need to get it to work
            }
    ]);

The problem is that MyService1 and MyService2 are not passed to the link function (ie if I only had a link function with scope, element, attrs then the code above would work just fine). How can I pass those variables as well?

I tried to call the function as link: link(scope, element, attrs, MyService1, MyService2) but then it says scope, element, attrs are undefined.

Note I realize that the someEmbeddedFunction can right now be moved out without a problem. This was just for demonstrating purposes.

Edit

The only way I can think to get this to work is call the link function from the directive this way:

link: function(scope, element, attrs) { 
    link(scope, element, attrs, MyService1, MyService2);
}

As you observed, the only way to call your non-standard link function is to do so manually within a "standard" link function.

ie

link: function(scope, element, attrs) { 
    link(scope, element, attrs, MyService1, MyService2);
}

This is because the link function doesn't get injected like other functions in Angular. Instead, it always gets the same series of arguments (regardless of what you call the function parameters):

  1. The scope
  2. The element (as an angular.element() instance)
  3. The attrs object
  4. An array or single controller instance that you require d
  5. A transclude function (if your directive uses transclusion)

Nothing else.

I use this scheme to keep it simple & readable:

var awesomeDir = function (MyService, MyAnotherService) {

    var someEmbeddedFunction = function () {
        MyService.doStuff();
    };

    var link = function ($scope, $elem, $attrs) {
        someEmbeddedFunction();
    };

    return {
        template: '<div>...</div>',
        replace: true,
        restrict: 'E',
        link: link
    };

};

awesomeDir.$inject = ['MyService', 'MyAnotherService'];

app.directive('awesomeDir', awesomeDir);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM