AngularJS TypeScript指令链接函数

时间:2014-05-17 12:07:20

标签: angularjs typescript

我试图使用TypeScript创建一个AngularJS指令。我的指令需要' ngModel'我也使用在我的指令中注入的自定义服务。 我的主要问题是我的服务无法在我的链接功能中使用。

以下是我试图实现的一个例子:

module app.directives {

    export var directiveName: string = "theDirective";

    angular.module("myApp").directive(directiveName, 
           (myFactory: app.services.MyFactory) =>
           {
                return new MyDirective(myFactory);
           });

    export interface IMyDirectiveScope extends ng.IScope {
        ngModel: ng.INgModelController;
    }

    export class MyDirective implements ng.IDirective {

        restrict = "A";
        require = "ngModel";
        scope = {
            ngModel:'='
        }

        constructor(private myFactory: app.services.MyFactory) {

        }


        link(scope: IMyDirectiveScope , elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) {
            //this is window here

            elem.bind('blur', (evt: JQueryEventObject) => {  
                 //keyword this is also window here, so yeah bummer indeed
                 validate(); 
            });

            function validate() {
                 //I need to use my factory here, but I can seem to get it.
                 //this is always window and I'm kinda stuck here
            }
        }
    }
}

我似乎无法在这个主题上找到一些更高级的东西。所有的例子都没有发现我似乎没有使用服务或复杂的链接功能。 请用某种方式回答这个问题。你认为这是一种诡计。

更新:这个'这个'在我的链接功能里面是窗口而不是' MyDirective'对我来说没有多大意义。任何想法为什么会这样?

2 个答案:

答案 0 :(得分:22)

使用类和继承自ng.IDirective是使用TypeScript的方法。

TypeScript支持EcmaScript 6中的胖箭头函数() =>。 它是一种速记语法,也会改变this关键字的工作方式:

class MyDirective implements ng.IDirective {
    restrict = 'A';
    require = 'ngModel';
    scope = {
        ngModel: '='
    }

    constructor(private myFactory: app.services.MyFactory) {
    }

    link = (scope: IMyDirectiveScope, elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) => {
        console.log(this); // this points to MyDirective instance instead of Window

        elem.bind('blur', (evt: JQueryEventObject) => {
            console.log(this); // this points to MyDirective instance instead of Window
            this.validate(); 
        });
    }

    validate() {
        console.log(this); // this points to MyDirective instance instead of Window
    }


    static factory(): ng.IDirectiveFactory {
        var directive = (myFactory: app.services.MyFactory) => new MyDirective(myFactory);
        directive.$inject = ['myFactory'];
        return directive;
    }
}

app.directive('mydirective', MyDirective.factory());

您还可以依赖旧时尚var self = this;模式:

class MyDirective implements ng.IDirective {
    restrict = 'A';
    require = 'ngModel';
    scope = {
        ngModel: '='
    }

    constructor(private myFactory: app.services.MyFactory) {
    }

    link = (scope: IMyDirectiveScope, elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) => {
        console.log(this); // this points to MyDirective instance instead of Window

        var self = this;

        function validate() {
            console.log(self); // self points to MyDirective instance
        }

        elem.bind('blur', function(evt: JQueryEventObject) {
            console.log(self); // self points to MyDirective instance
            validate(); 
        });
    }
}

相关答案:https://stackoverflow.com/a/29223535/990356

答案 1 :(得分:16)

类对控制器和指令控制器很有用,但我不认为我会使用一个用于整个指令。但如果你想要你可能不得不做这样的事情:

export class MyDirective implements ng.IDirective {

    public link;

    restrict = "A";
    require = "ngModel";
    scope = {
        ngModel:'='
    }

    constructor(private myFactory: app.services.MyFactory) {
        this.link = this.unboundLink.bind(this);
    }


    unboundLink(scope: IMyDirectiveScope , elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) {
        //Now you should be able to access myFactory
        this.myFactory.doSomething();

        elem.bind('blur', (evt: JQueryEventObject) => {  
             //keyword this is also window here, so yeah bummer indeed
             validate(); 
        });

        function validate() {
             //I need to use my factory here, but I can seem to get it.
             //this is always window and I'm kinda stuck here
        }
    }
}

编辑:没有课,你可以这样做:

angular.module("myApp").directive("theDirective", 
    function(myFactory: app.services.MyFactory) {
        return {
            restrict: 'A',
            require: 'ngModel',
            scope: {'ngModel': '='},
            link: function(scope: IMyDirectiveScope , elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) {
                //You can access myFactory like this.
                myFactory.doSomething();
            }
        }
    }
);