使用 TypeScript 和注入的 AngularJS 过滤器
Posted
技术标签:
【中文标题】使用 TypeScript 和注入的 AngularJS 过滤器【英文标题】:AngularJS Filter with TypeScript and injection 【发布时间】:2015-09-15 02:00:35 【问题描述】:谁能给我一个例子,说明我如何在 TypeScript 中创建一个使用依赖注入的 Angular 过滤器。底部是我目前拥有的,工作正常,但我想要做的是我想要访问 $filter 的函数,以便我可以将行 return date.ToString() 更改为 $filter '日期'。这样我就可以使用内置的日期过滤器来显示一个友好的短日期。
class FriendlyDateFilter
public static Factory()
return function (input): string
if (angular.isDate(input))
var date: Date = input;
var today = new Date();
var days = Math.abs(getDaysBetweenDates(today, date));
if (days < 7)
var dayInWeek = date.getDay();
switch (dayInWeek)
case 0:
return "Sunday";
break;
case 1:
return "Monday";
break;
case 2:
return "Tuesday";
break;
case 3:
return "Wednesday";
break;
case 4:
return "Thursday";
break;
case 5:
return "Friday";
break;
case 6:
return "Saturday";
break;
else
return date.toString();
else
return input;
function getDaysBetweenDates(d0, d1)
var msPerDay = 8.64e7;
// Copy dates so don't mess them up
var x0: any = new Date(d0);
var x1: any = new Date(d1);
// Set to noon - avoid DST errors
x0.setHours(12, 0, 0);
x1.setHours(12, 0, 0);
// Round to remove daylight saving errors
return Math.round((x1 - x0) / msPerDay);
angular.module("ReadingLog").filter("FriendlyDateFilter", FriendlyDateFilter.Factory);
【问题讨论】:
将 $filter 作为参数添加到工厂函数?这就是你在 JS 中的做法。 是的,我认为这是我需要的,但我还需要在某处/以某种方式使用 $inject,这就是我不明白该怎么做。 在 JS 中,你会做FriendlyDateFilter.Factory.$inject = ['$filter']
。或者你什么都不做,只在构建过程中使用 ng-annotate。
我不知道在我的 TypeScript 类中我可以把它放在哪里。
【参考方案1】:
你可以使用类来注入依赖,只需要在模块中使用 [] 并使用方法注入如下:
module Filters
export class MyFilter
public static Factory(injectableService: InjectableService)
return function (input:any)
// use injectableService to affect your input in desired way
return input;
angular.module('app')
.filter('myFilter', ['injectableService', MyFilter.Factory]);
【讨论】:
【参考方案2】:首先,您需要使用angular.d.ts
definition file。
然后,您只需执行以下操作:
MyFilter.$inject = ["$log"];
function MyFilter ($log: ng.ILogService): Function
return function(msg: string)
$log.log("I'm injected!");
return msg;
;
angular.module("testModule").filter("MyFilter", MyFilter);
$inject
属性在Function
中可用,这要归功于angular.d.ts
中的这些行:
// Support for painless dependency injection
interface Function
$inject?: string[];
见https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/angularjs/angular.d.ts#L12
【讨论】:
【参考方案3】:我在为 AngularJs 1.3 和 Typescript 编写自己的 DI 系统时遇到了同样的问题。为了解决这个问题,我编写了一个装饰器,它接受一个实现以下接口的类:
interface IFilter
filter(value?: any, ...args): any;
它使用以下代码注册过滤器:
var filterFactory = (...args) =>
var filterObject = new target(...args);
if (typeof filterObject.filter === 'function')
return filterObject.filter.bind(filterObject);
console.warn('Invalid filter: filter() method not found for:', filterName)
return function() ; //dummy filter, so it won't break everything
;
var constructorArray: Array<any> = injector.resolveParamNames(target);
app.filter(filterName, constructorArray.concat(filterFactory));
我的库使用自定义版本的 TypeScript 编译器,它能够发出接口元数据,injector.resolveParamNames
使用该元数据来构建像这样的经典构造函数数组:['$q', '$timeout', FilterFactory]
您可以找到我的项目here,以及过滤器示例here
【讨论】:
【参考方案4】:在编写 Angular 过滤器时,通常最好使用 function
+module
而不是 class
。您可以像这样构造代码:
function FriendlyDateFilter($filter)
return function (s: string): string
/* Your logic here */
/* Helper logic here */
module FriendlyDateFilter
export var $inject = ['$filter'];
angular.module("ReadingLog").filter("FriendlyDateFilter", FriendlyDateFilter);
如果您想避免向全局范围添加太多内容,也可以将两个 FriendlyDateFilter
声明放在另一个 module
中。
【讨论】:
为什么不简单地使用FriendlyDateFilter.$inject = ['$filter']
而不是使用带有导出变量的模块?
你可以使用 FriendlyDateFilter['$inject'] = ...
但 TypeScript 不允许在没有某种声明的情况下使用点语法
它将与来自DefiniteTyped 的angular.d.ts 一起使用,请参阅github.com/DefinitelyTyped/DefinitelyTyped/blob/master/…
@adripanico 如果您觉得我的回答有用,请点赞:)
我做到了!再次感谢。以上是关于使用 TypeScript 和注入的 AngularJS 过滤器的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 TypeScript 静态注入器模式注入`$rootScope`?
在 Angular2 中使用生成的 Swagger TypeScript Rest Client
AngularJS 和 Typescript - 注入其他服务的服务未定义