ngts-annotations
TypeScript 1.8+ annotations (decorators) for AngularJS 1.5.x
What ?
ngts-annotations provides annotation like decorators:
@Service()
@Inject(dependencyOne: string, ...dependencies?: string[])
@Controller()
@Directive(config: IDirectiveConfig)
@Factory()
@Resource()
@Component(config: IComponentConfig)
Why ?
Purpose of those decorators is to remove some ugly boilerplate from AngularJS applications written in TypeScript.
How ?
Service
Without annotations we have to:
export class SomeService {
constructor ( ) {
}
public someMethod ( anArg : number ) : boolean {
}
}
and in the main module:
import { SomeService } from ' some.service.ts ' ;
export someModule = angular . module ( ' someModule ' , [ ] ) . service ( ' someService ' , SomeService ) ;
Using ngts-annotations it will look like:
@ Service ( )
export class SomeService {
constructor ( ) {
}
public someMethod ( anArg : number ) : boolean {
}
}
and in the main module:
import { SomeService } from ' some.service.ts ' ;
export someModule = autoDeclare ( ' someModule ' , [] , [ SomeService ]) ;
Inject
Without annotations we have to:
export class SomeService {
static $inject = [ ' $http ' , ' $parse ' ] ;
constructor (
private $http : angular . IHttpService ,
private $parse : angular . IParseService
) {
}
public someMethod ( anArg : number ) : boolean {
}
}
and in the main module:
import { SomeService } from ' some.service.ts ' ;
export someModule = angular . module ( ' someModule ' , [ ] ) . service ( ' someService ' , SomeService ) ;
Using ngts-annotations it will look like:
@ Service ( )
export class SomeService {
constructor (
@ Inject ( ' $http ' ) $http : angular . IHttpService ,
@ Inject ( ' $parse ' ) private $parse : angular . IParseService
) {
}
public someMethod ( anArg : number ) : boolean {
}
}
or
@ Service ( )
@ Inject ( ' $http ' , ' $parse ' )
export class SomeService {
constructor (
private $http : angular . IHttpService ,
private $parse : angular . IParseService
) {
}
public someMethod ( anArg : number ) : boolean {
}
}
and in the main module:
import { autoDeclare } from ' ngts-annotations/src/at-angular ' ;
import { SomeService } from ' some.service.ts ' ;
export someModule = autoDeclare ( ' someModule ' , [] , [ SomeService ]) ;
Controller
Without annotations we have to:
export class SomeController {
static $inject = [ ' $scope ' , ' $parse ' ] ;
constructor (
private $scope : IScope ,
private $parse : IParseService
) {
}
public someMethod ( anArg : number ) : boolean {
}
}
and in the main module:
import { SomeService } from ' some.service.ts ' ;
export someModule = angular . module ( ' someModule ' , [ ] ) . service ( ' someController ' , SomeController ) ;
Using ngts-annotations it will look like:
@ Controller ( )
export class SomeController {
constructor (
@ inject ( ' $scope ' ) private $scope : angular . IScope ,
@ inject ( ' $parse ' ) private $parse : angular . IParseService
) {
}
public someMethod ( anArg : number ) : boolean {
}
}
and in the main module:
import { SomeService } from ' some.service.ts ' ;
export someModule = autoDeclare ( ' someModule ' , [] , [ SomeController ]) ;
Directive
Without annotations we have to do:
class TestDirective {
name : string ;
constructor ( private $scope : IFirstComponentScope ,
private $parse : IParseService ) {
$scope . name = this . name = ' FirstTestCtrl ' ;
}
setCtrlName ( name : string ) : void {
this . $parse ( ' name ' ) . assign ( this , name ) ;
}
}
export const testDirectiveConfig = {
name : ' testDirective ' ,
restrict : ' E ' ,
link : ( scope , element , attrs , ctrl : TestDirective ) => {
element . addClass ( ' test-component ' ) ;
ctrl . setCtrlName ( ' FAKE_CTRL_NAME ' ) ;
} ,
controller : TestDirective
controllerAs : ' ctrl ' ,
template : ' <span>{{ name }}</span><span>{{ ctrl.name }}</span> '
} ;
and in the main module:
import { SomeService } from ' some.service.ts ' ;
export someModule = angular . module ( ' someModule ' , [ ] ) . service ( ' testDirective ' , testDirectiveConfig ) ;
Using ngts-annotations it will look like:
@ Directive ( {
name : ' testDirective ' ,
restrict : ' E ' ,
link : ( scope , element , attrs , ctrl : TestDirective ) => {
element . addClass ( ' test-component ' ) ;
ctrl . setCtrlName ( ' FAKE_CTRL_NAME ' ) ;
} ,
controllerAs : ' ctrl ' ,
template : ' <span>{{ name }}</span><span>{{ ctrl.name }}</span> '
} )
export class TestDirective {
name : string ;
constructor ( @ Inject ( ' $scope ' ) private $scope : IFirstComponentScope ,
@ Inject ( ' $parse ' ) private $parse : IParseService ) {
$scope . name = this . name = ' FirstTestCtrl ' ;
}
setCtrlName ( name : string ) : void {
this . $parse ( ' name ' ) . assign ( this , name ) ;
}
}
and in the main module:
import { TestDirective } from ' test.directive.ts ' ;
export someModule = autoDeclare ( ' someModule ' , [] , [ TestDirective ]) ;
Factory
If you use constructors/classes to create common entities a @ClassFactory
can be useful.
It passes constructor as angular service and attaches $inject
's to it's prototype with leading $
.
import { Factory , Inject } from ' ../src/at-angular ' ;
import IParseService = angular . IParseService ;
import IHttpService = angular . IHttpService ;
@ Factory ( )
@ Inject ( ' $http ' , ' $parse ' )
export class TestFactory {
public accept : string ;
$http : IHttpService ;
$parse : IParseService ;
constructor ( ) {
this . accept = this . $parse ( ' defaults.headers.common.Accept ' ) ( this . $http ) ;
}
}
then somewhere else:
…
constructor ( ) {
this . testFactory = new TestFactory ( ) ;
}
…
and finally in the main module:
import { TestFactory } from ' test.factory.ts ' ;
export someModule = autoDeclare ( ' someModule ' , [] , [ TestFactory ]) ;
Resource
This one is somehow similar to @ClassFactory
, but it also encapsulates magic powers of angular $resource
.
$resource
configs are gathered from static class members.
import { Resource , BaseResource } from " ../src/at-angular-resource " ;
import { Inject } from " ../src/at-angular " ;
import IHttpService = angular . IHttpService ;
import IParseService = angular . IParseService ;
interface IUser {
name : string ;
age : number ;
}
@ Resource ( )
@ Inject ( ' $http ' , ' $parse ' )
export class UserResource extends BaseResource implements IUser {
static url : string = ' /fake/url ' ;
name : string ;
age : number ;
private $http : IHttpService ;
private $parse : IParseService ;
constructor ( model ? : IUser ) {
super ( model ) ;
if ( model ) {
this . name = model . name ;
this . age = model . age ;
}
}
getLabel ( ) : string {
return this . $parse ( ' defaults.headers.common.Accept ' ) ( this . $http ) + this . name + String ( this . age ) ;
}
}