似乎有很多方法可以在TypeScript中创建Angular指令。我唯一看到的是使用静态工厂函数:
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());
}
但是如果我需要注射东西,我不知道该怎么办。说我想要$ timeout:
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构造函数并传入$ timeout。
答案 0 :(得分:4)
只需指定$timeout
作为工厂构造函数参数并传递它。
static factory(): ng.IDirectiveFactory {
var directive: ng.IDirectiveFactory =
($timeout:ng.ITimeoutService) => new myDirective($timeout);
directive.$inject = ["$timeout"];
return directive;
}
答案 1 :(得分:0)
虽然有一个公认的答案,但我想给我两分钱。 前段时间我对指令有同样的问题,但也有过滤器(Angular注册过滤器工厂),所以我决定围绕标准类型定义构建一个小型库,允许我写这样的东西(控制和模板代码是省略):
@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);
}
}
为了实现这一点,我必须自定义TypeScript代码发射器,现在它生成接口元数据(ng.IQService
在运行时可用并映射到构造函数数组中的'$q'
;元数据由@Directive
装饰器使用,该装饰器使用this code在应用程序模块中注册指令。
您可以查看示例应用程序代码here。
答案 2 :(得分: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
和static $inject
。您必须按PSL所述指定注入:
// ...
class SampleDirective implements ng.IDirective {
public static $inject: string[] = ["$timeout"];
// ...
constructor(private $timeout:ng.ITimeoutService) {
// ...
这样可以避免重复工厂方法,并且您可以始终使用相同的模式......
答案 3 :(得分: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'];
&#13;