web-dev-qa-db-fra.com

Comment définir une fabrique AngularJS à l'aide d'une classe TypeScript comportant des paramètres de constructeur

Je veux écrire une classe TypeScript qui obtient un paramètre "préfixe" dans le constructeur. Cette classe doit également accéder à un inject LogService.

En utilisant du JavaScript simple, vous devriez le faire comme ceci:

angular.module('myModule', []).factory('LogWithPrefixFactory', ['LogService', function(LogService) {
    var LogWithPrefixFactory = function(prefix) {
        this.prefix = prefix;
    }

    LogWithPrefixFactory.prototype.log = function(txt) {
        // we have access to the injected LogService
        LogService.log(this.prefix, txt);
    }

    return LogWithPrefixFactory;
}]);

Ainsi, lorsque vous injectez cette fabrique dans un contrôleur, vous pouvez l’initialiser plusieurs fois de la manière suivante (inutile d’injecter LogService):

angular.module('myModule').controller('Ctrl', function(LogWithPrefixFactory) {
    var foo = new LogWithPrefixFactory("My PREFIX");
    var foo = new LogWithPrefixFactory("My OTHER PREFIX");
}

Comment définiriez-vous cette fabrique dans une classe TypeScript?.

17
gilamran

Il y a au moins 2 options.

Première option, LogWithPrefixFactory fournisse une méthode getInstance qui renvoie le consignateur préfixé.

module services {
  class LogService {
    $window: any;

    constructor($window: any) {
      this.$window = $window;
    }

    log(prefix: string, txt: string) {
      this.$window.alert(prefix + ' :: ' + txt);
    }
  }
  angular.module('services').service('LogService', ['$window', LogService]);


  export interface ILog {
    log: (txt) => void;
  }

  export class LogWithPrefixFactory {
    logService: LogService;

    constructor(logService: LogService) {
      this.logService = logService;
    }

    getInstance(prefix: string): ILog {
      return {
        log: (txt: string) => this.logService.log(prefix, txt);
      }
    }
  }

  angular.module('services').service('LogWithPrefixFactory', ['LogService', services.LogWithPrefixFactory]);
}

Ce qui peut être utilisé dans le contrôleur comme:

this.log1 = logWithPrefixFactory.getInstance("prefix1");
this.log2 = logWithPrefixFactory.getInstance("prefix2");

Plunker complet ici .

Deuxième option (semblable à une autre réponse), donnez Angular une autre fonction à utiliser en tant que constructeur, qui gère manuellement l'injection de constructeur LogService (personnellement, je n'aime pas static).

angular.module('services').service('LogWithPrefixFactory', ['LogService', function(logService) {
    return function LogWithPrefixFactory(prefix) {
      return new LogWithPrefix(prefix, logService);
    };
}]);

Ce qui peut être utilisé dans le contrôleur comme:

this.log1 = new LogWithPrefixFactory("prefix1");
this.log2 = new LogWithPrefixFactory("prefix2");

ou même: 

this.log1 = LogWithPrefixFactory("prefix1");
this.log2 = LogWithPrefixFactory("prefix2");

LogWithPrefixFactory est injecté dans le contrôleur mais ce n'est pas le constructeur de la classe TypeScript, c'est la fonction intermédiaire qui renvoie l'instance réelle de la classe, après que celle-ci a été injectée "manuellement" avec LogService.

Plunker complet ici .

Note: Ces boutons compilent de manière synchrone TypeScript sur le navigateur. Je l'ai testé uniquement sur Chrome. Aucune garantie qu'ils vont fonctionner. Enfin, j'ai ajouté manuellement une petite partie de angular.d.ts. Le fichier complet était très volumineux et mon proxy n'autorisait pas les gros POST.

13
Kos Prov

Voici un moyen d'y parvenir: 

class LogWithPrefixFactory {
    static LogService;
    constructor(prefix) {
        this.prefix = prefix;
    }

    log = function(txt) {
        // we have access to the injected LogService
        LogService.log(this.prefix, txt);
    }
}

angular.module('myModule', []).factory('LogWithPrefixFactory', ['LogService', function(LogService) {
    LogWithPrefixFactory.LogService = LogService;
    return LogWithPrefixFactory;
}]);


angular.module('myModule').controller('Ctrl', function(LogWithPrefixFactory) {
    var foo = new LogWithPrefixFactory("My PREFIX");
    var foo = new LogWithPrefixFactory("My OTHER PREFIX");
});

Rational: Vous voulez effectivement une propriété statique dans un LogWithPrefixFactory (à l'aide d'une fermeture dans JS), et vous voulez qu'elle vienne de Angular.

20
basarat

J'ai réalisé comme ci-dessous

module Dashboard {
    export class LayoutServiceFactory {
        static $inject = ["$q", "$http"];
        private q: ng.IQService;
        private http: ng.IHttpService;

        constructor(private $q: ng.IQService, private $http: ng.IHttpService) {
            this.q = $q;
            this.http = $http;
        }

        getDataFromServer(serviceUrl) {
            var deferred = this.q.defer();
            this.http.get(serviceUrl, null)
                .then(response => {

                    deferred.resolve((response) as any);

                });
            return deferred.promise;
        }

        static factory() {
            var instance = ($q: ng.IQService, $http: ng.IHttpService) =>
                new LayoutServiceFactory($q, $http);
            return instance;
        }
    }

    appModule.factory("LayoutService", LayoutServiceFactory.factory());
}
7
Code-EZ

Cela a fonctionné pour moi.

    namespace Services
    {
      export class MyService
      {
        constructor( protected $someService :any )
        {
          return this;
        }
      }
    }
    angular.module( 'myModule', [] ).factory( Services );
2
diashes

Vous pouvez créer un type qui vous permet de définir le constructeur de la fabrique:

// Defining the factory

// THIS IS THE IMPORTANT PART!!
export type SelectorFactory = new (config: any) => Selector;

export class Selector {

    constructor(protected config: any, protected $http: ng.IHttpService) {
        // do some stuff
    }
}

angular.module('app')
    .factory('Selector', ($http: ng.IHttpService) => {
        // This is what the factory looks like to the end user
        return (config: any) => {
            return new Selector(config, $http);
        };
    });

// Using the factory
export class SampleCtrl {
    constructor(public SelectorFactory: SelectorFactory) {
        let config = { op: 1 };

        let selector: Selector = new SelectorFactory(config);
    }
}
1
Andreas Stocker

voici comment je le fais 

 namespace app {
             let app =angular.module('foo',[]);
               app.factory(factories);//for registering whatever is there in factories namespace

      }

 namespace app.factories {


 export class fooFactory {

    static $inject = ['fooHelperService']
    constructor(fooHelperService: services.fooHelperService) {

        return {

            fooFunc: () => {

               return 'hellow world'
            }
        }
    }
 }

}
1
Pranay Dutta