Définir la directive AngularJS en utilisant le mécanisme TypeScript et $ inject

Récemment, j’ai commencé à refactoriser l’un des projets Angular sur lesquels je travaille avec TypeScript. L’utilisation de classes TypeScript pour définir des contrôleurs est très pratique et fonctionne bien avec les fichiers JavaScript minifiés grâce à static $inject Array propriété static $inject Array . Et vous obtenez un code assez propre sans séparer les dépendances angulars de la définition de classe:

  module app { 'use ssortingct'; export class AppCtrl { static $inject: Array  = ['$scope']; constructor(private $scope) { ... } } angular.module('myApp', []) .controller('AppCtrl', AppCtrl); } 

En ce moment, je cherche une solution pour gérer des cas similaires pour la définition de la directive. J’ai trouvé une bonne pratique pour définir les directives comme fonction:

 module directives { export function myDirective(toaster): ng.IDirective { return { ressortingct: 'A', require: ['ngModel'], templateUrl: 'myDirective.html', replace: true, link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAtsortingbutes, ctrls) => //use of $location service ... } }; } angular.module('directives', []) .directive('myDirective', ['toaster', myDirective]); } 

Dans ce cas, je suis obligé de définir des dépendances angulars dans la définition de la directive, qui peut être très sujette aux erreurs si la définition et la classe TypeScript se trouvent dans des fichiers différents. Quelle est la meilleure façon de définir des directives avec typecript et le mécanisme $inject , je cherchais un moyen de mettre en œuvre l’interface TypeScript IDirectiveFactory mais je n’étais pas satisfait des solutions trouvées.

    Utiliser des classes et hériter de ng.IDirective est la voie à suivre avec TypeScript:

     class MyDirective implements ng.IDirective { ressortingct = '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.IAtsortingbutes, 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()); 

    Réponse connexe: https://stackoverflow.com/a/29223360/990356

    Je préfère spécifier un controller pour la directive et y injecter uniquement les dépendances .

    Avec le contrôleur et son interface en place, je tape fortement le 4ème paramètre de la fonction de liaison sur l’interface de mon contrôleur et je profite de son utilisation à partir de là.

    Le fait de déplacer le problème de dépendance de la partie link vers le contrôleur de la directive me permet de bénéficier de TypeScript pour le contrôleur, tout en gardant ma fonction de définition de directive courte et simple (contrairement à l’approche de classe directive qui requirejs ):

     module app { "use ssortingct"; interface IMyDirectiveController { // specify exposed controller methods and properties here getUrl(): ssortingng; } class MyDirectiveController implements IMyDirectiveController { static $inject = ['$location', 'toaster']; constructor(private $location: ng.ILocationService, private toaster: ToasterService) { // $location and toaster are now properties of the controller } getUrl(): ssortingng { return this.$location.url(); // utilize $location to resortingeve the URL } } function myDirective(): ng.IDirective { return { ressortingct: 'A', require: 'ngModel', templateUrl: 'myDirective.html', replace: true, controller: MyDirectiveController, controllerAs: 'vm', link: (scope: ng.IScope, element: ng.IAugmentedJQuery, atsortingbutes: ng.IAtsortingbutes, controller: IMyDirectiveController): void => { let url = controller.getUrl(); element.text('Current URL: ' + url); } }; } angular.module('myApp'). directive('myDirective', myDirective); } 

    Dans ce cas, je suis obligé de définir des dépendances angulars dans la définition de la directive, ce qui peut être très sujet aux erreurs si la classe de définition et de type est dans des fichiers différents.

    Solution:

      export function myDirective(toaster): ng.IDirective { return { ressortingct: 'A', require: ['ngModel'], templateUrl: 'myDirective.html', replace: true, link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAtsortingbutes, ctrls) => //use of $location service ... } }; } myDirective.$inject = ['toaster']; // THIS LINE 

    Cet article le couvre à peu près et la réponse de tanguy_k est à peu près textuellement l’exemple donné dans l’article. Il a également toutes les motivations de POURQUOI vous voudriez écrire la classe de cette façon. Héritage, vérification de type et autres bonnes choses …

    http://blog.aaronholmes.net/writing-angularjs-directives-as-typescript-classes/