Подтвердить что ты не робот

AngularJS TypeScript функция директивной ссылки

Я пытаюсь создать директиву AngularJS с помощью TypeScript. Моя директива требует "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
            }
        }
    }
}

Я не могу найти более продвинутые материалы по этой теме. Все примеры, которые я не обнаружил, похоже, не используют службы или сложную функцию связи. Пожалуйста, ответьте на этот вопрос каким-то примером. Это обман, который вы думаете.

Обновление: Тот факт, что 'this' внутри моей функции ссылки является окном, а не "MyDirective", не имеет для меня большого смысла. Любые идеи, почему это было бы?

4b9b3361

Ответ 1

Классы отлично подходят для контроллеров и контроллеров директив, но я не думаю, что буду использовать их для всей директивы. Но если вы захотите, вам, вероятно, придется сделать что-то вроде этого:

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
        }
    }
}

EDIT: Без класса вы можете сделать что-то вроде этого:

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();
            }
        }
    }
);

Ответ 2

Использование классов и наследование из 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(); 
        });
    }
}

Связанный ответ: fooobar.com/info/144438/...