Recently I started refactoring one of the Angular projects I am working on with TypeScript. Using TypeScript classes to define controllers is very convenient and works well with minified JavaScript files thanks to static $inject Array<string>
property. And you get pretty clean code without splitting Angular dependencies from the class definition:
module app {
'use strict';
export class AppCtrl {
static $inject: Array < string > = ['$scope'];
constructor(private $scope) {
...
}
}
angular.module('myApp', [])
.controller('AppCtrl', AppCtrl);
}
Right now I am searching for solution to handle similar case for the directive definition. I found a good practice to define the directives as function:
module directives {
export function myDirective(toaster): ng.IDirective {
return {
restrict: 'A',
require: ['ngModel'],
templateUrl: 'myDirective.html',
replace: true,
link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrls) =>
//use of $location service
...
}
};
}
angular.module('directives', [])
.directive('myDirective', ['toaster', myDirective]);
}
In this case I am forced to define Angular dependencies in the directive definition, which can be very error-prone if the definition and TypeScript class are in different files. What is the best way to define directive with typescript and the $inject
mechanism, I was searching for a good way to implement TypeScript IDirectiveFactory
interface but I was not satisfied by the solutions I found.
Using classes and inherit from ng.IDirective is the way to go with TypeScript:
class MyDirective implements ng.IDirective {
restrict = 'A';
require = 'ngModel';
templateUrl = 'myDirective.html';
replace = true;
constructor(private $location: ng.ILocationService, private toaster: ToasterService) {
}
link = (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrl: any) => {
console.log(this.$location);
console.log(this.toaster);
}
static factory(): ng.IDirectiveFactory {
const directive = ($location: ng.ILocationService, toaster: ToasterService) => new MyDirective($location, toaster);
directive.$inject = ['$location', 'toaster'];
return directive;
}
}
app.directive('mydirective', MyDirective.factory());
Related answer: https://stackoverflow.com/a/29223360/990356