2015-06-12 37 views
6

Sembra esserci un numero di modi per creare direttive angolari in TypeScript. Il più grazioso che ho visto è quello di utilizzare una funzione di fabbrica statica:Iniezione dipendenza direttiva angolare - 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()); 
} 

Ma io non sono sicuro di cosa fare se ho bisogno di iniettare qualcosa. Di 'Mi piacerebbe $ 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()); 
} 

Come potete vedere sopra, non sono sicuro di come chiamare il contructor myDirective e passare a $ timeout.

+0

Perché sei, sovrapposizioni i propri moduli in cima angolare? Quale beneficio ottieni da questo ulteriore livello di complessità, stato globale aggiuntivo e duplicazione semantica ?. – yangmillstheory

risposta

4

Specificare semplicemente $timeout come argomento della funzione costruttore di fabbrica e passarlo.

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

Semplice come quello! Grazie! – user888734

+0

@ user888734 Prego. :) – PSL

+0

Non potevo farlo senza il tuo aiuto, grazie – deadManN

0

Anche se v'è una risposta accettata Mi piacerebbe dare i miei due centesimi .. Qualche tempo fa ho avuto lo stesso problema con la direttiva, ma anche con filtri (che registra angolari con fabbriche filtro), così ho decise di costruire una piccola biblioteca attorno alle definizioni di tipo standard che mi ha permesso di scrivere qualcosa del genere (controllato e codice modello viene omesso):

@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); 
    } 

} 

al fine di rendere questo possibile ho dovuto personalizzare il codice dattiloscritto emettitore e ora produce i metadati dell'interfaccia (che ng.IQService è disponibile in fase di runtime e mappato a '$q' nell'array costruttore); i metadati vengono utilizzati dal decoratore @Directive che registra la direttiva nel modulo dell'applicazione con this code. Puoi dare un'occhiata al codice dell'applicazione di esempio here.

0

Ho affrontato lo stesso problema e risolto mediante l'attuazione di una classe Util chiamato "ComponentRegistrator" (ispirato dai commenti 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; 
     } 
    } 
} 

e questo può per esempio essere utilizzato come segue:

/// <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); 
} 

Nota la return this nel construcotor e static $inject. Si dovrà specificare l'iniettare come descritto da PSL:

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

In questo modo la duplicazione del metodo fabbrica può essere evitato e si può sempre utilizzare lo stesso modello ...

0

Un po 'più semplice, a mio parere:

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'];