2015-06-12 82 views
6

似乎有很多方法可以在TypeScript中創建Angular指令。我見過的最好的是使用靜態工廠功能:Angular指令依賴注入 - TypeScript

module app { 
    export class myDirective implements ng.IDirective { 
     restrict: string = "E"; 
     replace: boolean = true; 
     templateUrl: string = "my-directive.html"; 

     link: ng.IDirectiveLinkFn = (scope: ng.IScope, el: ng.IAugmentedJQuery, attrs: ng.IAttributes) => { 
     }; 

     static factory(): ng.IDirectiveFactory { 
      var directive: ng.IDirectiveFactory =() => new myDirective(); 
      return directive; 
     } 
    } 

    angular.module("app") 
     .directive("myDirective", myDirective.factory()); 
} 

但我不知道如果我需要注入什麼,該怎麼辦。說我想$超時:

module app { 
    export class myDirective implements ng.IDirective { 
     restrict: string = "E"; 
     replace: boolean = true; 
     templateUrl: string = "my-directive.html"; 

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

     link: ng.IDirectiveLinkFn = (scope: ng.IScope, el: ng.IAugmentedJQuery, attrs: ng.IAttributes) => { 
      // using $timeout 
      this.$timeout(function(): void { 
      }, 2000); 
     } 

     static factory(): ng.IDirectiveFactory { 
      var directive: ng.IDirectiveFactory =() => new myDirective(); // Uhoh! - What's goes here? 
      directive.$inject = ["$timeout"]; 
      return directive; 
     } 
    } 

    angular.module("app") 
     .directive("myDirective", myDirective.factory()); 
} 

正如你可以在上面看到,我不知道如何調用myDirective構造器,並通過在$超時。

+0

你爲什麼對角頂分層你自己的模塊?你從這個額外的複雜層面,額外的全局狀態和語義重複中獲得了什麼好處? – yangmillstheory

回答

4

只需指定$timeout作爲工廠構造函數參數並傳遞即可。

static factory(): ng.IDirectiveFactory { 
     var directive: ng.IDirectiveFactory = 
         ($timeout:ng.ITimeoutService) => new myDirective($timeout); 
     directive.$inject = ["$timeout"]; 
     return directive; 
    } 
+1

就這麼簡單!謝謝! – user888734

+0

@ user888734不客氣。 :) – PSL

+0

沒有你的幫助,我無法做到,謝謝 – deadManN

0

雖然是一個公認的答案,我想給我的兩分錢.. 有時前,我曾與指令同樣的問題,也與過濾器(帶過濾器的工廠角寄存器),所以我決定建立各地的標準類型定義,讓我寫這樣的事情(控制,省略模板代碼)一個小型圖書館:

@Directive('userRank') 
export class UserRankDirective implements ng.IDirective { 

    controller = UserRankDirectiveController; 
    restrict = 'A'; 
    template = template; 
    //controllerAs: 'ctrl', set as default 
    replace = true; 
    scope = { 
     user: '=userRank' 
    } 

    constructor($q: ng.IQService) { 
     console.log('Q service in UserRankDirective:', $q); 
    } 

} 

爲了實現這一點,我不得不定製打字稿代碼發射器和現在它生成接口元數據(ng.IQService在運行時可用並被映射到構造函數數組中的'$q'); @Directive裝飾器使用元數據,該應用程序模塊中的指令註冊爲this code。 您可以查看示例應用程序代碼here

0

我面臨着同樣的問題,並通過實施所謂的「ComponentRegistrator」一類的Util解決它(通過評論on this page啓發):

/// <reference path="../../../Typings/tsd.d.ts"/> 
module Common.Utils { 
    "use strict"; 

    export class ComponentRegistrator { 
     public static regService(app: ng.IModule, name: string, classType: Function) { 
      return app.service(name, classType); 
     } 

     public static regController(app: ng.IModule, name: string, classType: Function) { 
      var factory: Function = Component.reg(app, classType); 
      return app.controller(name, factory); 
     } 

     public static regDirective(app: ng.IModule, name: string, classType: Function) { 
      var factory: Function = Component.reg(app, classType); 
      return app.directive(name, <ng.IDirectiveFactory>factory); 
     } 

     private static reg<T extends ng.IDirective>(app: ng.IModule, classType: Function) { 
      var factory: Function = (...args: any[]): T => { 
       var o = {}; 
       classType.apply(o, args) || console.error("Return in ctor missing!"); 
       return <T> o; 
      }; 
      factory.$inject = classType.$inject || []; 
      return factory; 
     } 
    } 
} 

,這可以如

/// <reference path="../../../Typings/tsd.d.ts"/> 
///<reference path="../../Common/Utils/Component.ts"/> 

module Sample { 
    "use strict"; 

    class SampleDirective implements ng.IDirective { 
     public static $inject: string[] = []; 

     public templateUrl: string; 
     public scope: {}; 
     public restrict: string; 
     public require: string; 
     public link: ng.IDirectiveLinkFn; 

     constructor() { 
      this.templateUrl = "/directives/sampleDirective.html"; 
      this.restrict = "A"; 
      this.scope = { 
       element: "=", 
      }; 
      this.link = this.linker; 
      return this; // important! 
     } 

     private linker = (scope: IExpressionConsoleScope): void => { 
      // ... 
     }; 
    } 

    ComponentRegistrator.regDirective(app, "directiveName", SampleDirective); 
} 

注意return this在construcotor和static $inject:如下使用。你將不得不指定注射由PSL描述:

// ... 
class SampleDirective implements ng.IDirective { 
    public static $inject: string[] = ["$timeout"]; 
// ... 
constructor(private $timeout:ng.ITimeoutService) { 
// ... 

這樣可避免工廠方法的重複,你總是可以使用相同的模式...

0

一點點簡單,在我看來:

export var SomeComponent = ($timeout: any): ng.IDirective => { 
 
    return { 
 
    controller, 
 
    controllerAs: 'vm', 
 
    restrict: 'E', 
 
    templateUrl: 'components/someTemplate/someTemplate.html', 
 
    scope: { 
 
     someAttribute: '@' 
 
    }, 
 
    link: { 
 
     post: (scope, elem, attr, ctrl) => { 
 
     console.log('Should see this here:', $timeout); 
 
     } 
 
    } 
 
    }; 
 
} 
 

 
SomeComponent.$inject = ['$timeout'];