2015-06-28 22 views
6

Qualcuno può fornirmi un esempio di come posso creare un filtro angolare in TypeScript che utilizza l'iniezione delle dipendenze. In fondo è quello che attualmente ho, che funziona bene, ma quello che voglio fare è la funzione che voglio avere accesso a $ filter, in modo che possa cambiare la data di ritorno della riga. ToString() in $ filter 'Data'. In questo modo, utilizzo il filtro data incorporato per mostrare una bella breve data amichevole.Filtro AngularJS con TypeScript e iniezione

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); 
+0

Aggiungi $ filtro come argomento per la funzione di fabbrica? Ecco come lo faresti in JS. –

+0

Sì, presumo che sia ciò di cui ho bisogno, ma ho anche bisogno di usare $ inject da qualche parte/in qualche modo e questo è quello che non capisco come fare. –

+0

In JS, si farebbe 'FriendlyDateFilter.Factory. $ Inject = ['$ filter']'. O non faresti altro che usare ng-annotate durante la compilazione. –

risposta

3

È generalmente meglio usare un function + module invece di un class quando si scrive un filtro angolare. È possibile strutturare il codice come questo:

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

Si potrebbe anche mettere entrambi i FriendlyDateFilter dichiarazioni all'interno di un altro module se si sta cercando di evitare di aggiungere troppo la portata globale.

+1

Perché non usare semplicemente 'FriendlyDateFilter. $ Inject = ['$ filter']' invece di usare un modulo con una var esportata? –

+1

Puoi usare 'FriendlyDateFilter ['$ inject'] = ...' ma TypeScript non permetterà la sintassi punteggiata senza alcun tipo di dichiarazione –

+0

Funzionerà con angular.d.ts da DefinitelyTyped, vedi https: // github. com/DefinitelyTyped/DefinitelyTyped/blob/master/angularjs/angular.d.ts # L12 –

0

Ho avuto lo stesso problema durante la scrittura del mio sistema DI per AngularJs 1.3 & Typescript. Per risolvere questo ho scritto un decoratore che accetta una classe che implementa l'interfaccia seguente:

interface IFilter { 
    filter(value?: any, ...args): any; 
} 

e registra il filtro con il seguente codice:

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

La mia libreria utilizza una versione personalizzata del dattiloscritto compilatore, che è in grado di emettere i metadati di interfaccia che viene utilizzato da injector.resolveParamNames per costruire la classica serie costruttore come questo: ['$q', '$timeout', FilterFactory]

potete trovare il mio progetto here, e un campione di filtro here

3

Innanzitutto, è necessario utilizzare angular.d.ts definition file.

Poi, è sufficiente effettuare le seguenti operazioni:

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 proprietà è disponibile in Function grazie a queste linee in angular.d.ts:

// Support for painless dependency injection 
interface Function { 
    $inject?: string[]; 
} 

Vedi https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/angularjs/angular.d.ts#L12

0

È possibile utilizzare le classi per iniettare dipendenze, basta usare [] nel modulo e utilizzare il metodo di iniezione come di seguito:

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]); 
Problemi correlati