How can I define an AngularJS factory using TypeScript class that has constructor parameters
angularjs, typescript
Solution
There are at least 2 options.
First option, have `LogWithPrefixFactory` provide a method `getInstance` that returns the prefixed logger.
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]);
}
Which can be used in the controller like:
this.log1 = logWithPrefixFactory.getInstance("prefix1");
this.log2 = logWithPrefixFactory.getInstance("prefix2");
Complete plunker here.
Second option (similar to another answer), give Angular another function to be used as a constructor, which handles manually the `LogService` constructor injection (personally, I don't like `static`).
angular.module('services').service('LogWithPrefixFactory', ['LogService', function(logService) {
return function LogWithPrefixFactory(prefix) {
return new LogWithPrefix(prefix, logService);
};
}]);
Which can be used in the controller like:
this.log1 = new LogWithPrefixFactory("prefix1");
this.log2 = new LogWithPrefixFactory("prefix2");
or even:
this.log1 = LogWithPrefixFactory("prefix1");
this.log2 = LogWithPrefixFactory("prefix2");
`LogWithPrefixFactory` is injected in the controller but it's not the TypeScript class constructor, it's the intermediate function which returns the actual instance of the class, after it has been "manually" injected with `LogService`.
Complete plunker here.
Note: These plunkers synchronously compile typescript on the browser. I have tested it only on Chrome. No guarantees that they'll work. Finally, I manually added a small part of angular.d.ts. Full file was very big and my proxy does not allow large POSTs.
Problem
I want to write a TypeScript class that gets a "prefix" parameter in the constructor, this class also needs access to a LogService inject. Using plain JavaScript you should do it like this: ``` 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; }]); ``` So when you inject this factory to a controller, you can initiate it many times like this (No need to inject the LogService): ``` angular.module('myModule').controller('Ctrl', function(LogWithPrefixFactory) { var foo = new LogWithPrefixFactory("My PREFIX"); var foo = new LogWithPrefixFactory("My OTHER PREFIX"); } ``` How would you define this Factory in a TypeScript class? TypeScript classes can not be defined inside functions... This class should have access to the LogService, but it can't get it in one of the injects.