最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Typescript $inject $timeout into a directive ... works in controller, not in link - Stack Overflow

programmeradmin1浏览0评论

Stack: Typescript 1.7 + Angular 1.49

Summary:

I have a directive. I want to $inject angular's $timeout service. It works fine in the directive's controller function, but not in the link function. What am I missing?

Questions:

  • What did I do wrong?
  • Is there a better way to $inject the $timeout dependency?
  • Why will the $timeout service work in the directive's controller but not the link?

MyDirective.ts:

module app.directives {

    export class MyDirective {
        priority = 0;
        restrict = 'E';
        templateUrl = 'template.html';
        scope = {
            'items': '='
        };
        controller = MyController;
        link = MyLink;

        static $inject = ['$timeout'];

        constructor(private  $timeout:ng.ITimeoutService) {
        }
    }

    function MyController($scope:ng.IScope, $timeout:ng.ITimeoutService) {
        console.log("controller", $timeout); // function timeout(fn,delay,invokeApply){ the guts here }
        $timeout(function () {
            console.log("This works fine");
        },3000);
    }

    function MyLink(scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes, $timeout:ng.ITimeoutService) {
        console.log("link to", $timeout); // MyController {}
        $timeout(function () {
            console.log("This throws the error, TypeError: $timeout is not a function");
        },3000);
    }
}

Connecting it in directives.ts:

module app.directives {
    angular.module('app').directive('MyDirective',['$timeout',($timeout:ng.ITimeoutService) => new MyDirective($timeout) ]);
}

app.ts

module app {
    angular.module('app', []);
}

What hasn't worked:

  • Using this.$timeout in MyLink, with or without including $timeout in the parameters.
  • I've found several articles and examples that I've tried to make sure I'm following the logic of in my app but can't seem to get it.

Final notes

  • Typescript-Angular is still new and there are so many best practices that are far from being defined. Part of my team's project is finding some of those.
  • We have been working on this general structure for a while, so unless there's a pelling reason, please refrain from suggestions that I change the structure of everything too much.

Stack: Typescript 1.7 + Angular 1.49

Summary:

I have a directive. I want to $inject angular's $timeout service. It works fine in the directive's controller function, but not in the link function. What am I missing?

Questions:

  • What did I do wrong?
  • Is there a better way to $inject the $timeout dependency?
  • Why will the $timeout service work in the directive's controller but not the link?

MyDirective.ts:

module app.directives {

    export class MyDirective {
        priority = 0;
        restrict = 'E';
        templateUrl = 'template.html';
        scope = {
            'items': '='
        };
        controller = MyController;
        link = MyLink;

        static $inject = ['$timeout'];

        constructor(private  $timeout:ng.ITimeoutService) {
        }
    }

    function MyController($scope:ng.IScope, $timeout:ng.ITimeoutService) {
        console.log("controller", $timeout); // function timeout(fn,delay,invokeApply){ the guts here }
        $timeout(function () {
            console.log("This works fine");
        },3000);
    }

    function MyLink(scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes, $timeout:ng.ITimeoutService) {
        console.log("link to", $timeout); // MyController {}
        $timeout(function () {
            console.log("This throws the error, TypeError: $timeout is not a function");
        },3000);
    }
}

Connecting it in directives.ts:

module app.directives {
    angular.module('app').directive('MyDirective',['$timeout',($timeout:ng.ITimeoutService) => new MyDirective($timeout) ]);
}

app.ts

module app {
    angular.module('app', []);
}

What hasn't worked:

  • Using this.$timeout in MyLink, with or without including $timeout in the parameters.
  • I've found several articles and examples that I've tried to make sure I'm following the logic of in my app but can't seem to get it.

Final notes

  • Typescript-Angular is still new and there are so many best practices that are far from being defined. Part of my team's project is finding some of those.
  • We have been working on this general structure for a while, so unless there's a pelling reason, please refrain from suggestions that I change the structure of everything too much.
Share Improve this question edited Mar 24, 2016 at 22:41 MaxRocket asked Mar 24, 2016 at 22:31 MaxRocketMaxRocket 9921 gold badge13 silver badges30 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

Link functions are not executed directly from directive instance, hence you wont get this as Directive's config instance (which you instantiate via new operator). Also you cannot inject anything to the link function (that is what directive constructor is for) unlike the controller constructor, the arguments to the link function are automatically passed in by the directive execution logic. You could use an arrow operator to resolve this issue.

Example:

 export class MyDirective {
    priority = 0;
    restrict = 'E';
    templateUrl = 'template.html';
    scope = {
        'items': '='
    };
    controller = MyController;

    link:ng.IDirectiveLinkFn = (scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes) => {

      //Here
      this.$timeout(function () {

      },3000);
    };

    constructor(private  $timeout:ng.ITimeoutService) {
    }
}

Or you could bind the context using function.bind. i.e link = MyLink; and access the $timeout using this.$timeout.

If interseted you could take a look at creating some syntactic sugars by using experimental decorators for directives or you could try exploring something like this. However (just my opinion) using a class for directive config seems to be an overkill, you might as well just use a function with static inject.

Link function 4th parameter is the controller instance him self.

If you want to do it you should do something like:

module app.directives {

    export class MyDirective {
        link = MyLink;

        static $inject = ['$timeout'];

        constructor(public $timeout:ng.ITimeoutService) {
        }
    }

    function MyLink(scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes, ctrl:any) {
        ctrl.$timeout(function () {
            console.log("This throws the error, TypeError: $timeout is not a function");
        },3000);
    }
}

I know that this is not elegant but I have hard time finding a better solution, what do you think?

发布评论

评论列表(0)

  1. 暂无评论