Giter Site home page Giter Site logo

angular-typescript's Introduction

Angular-TypeScript

GitHub version Build Status Coverage Status

npm version Dependency Status

Bower version Dependency Status

TypeScript 1.7+ annotations (decorators) for AngularJS 1.x

What ?

angular-typescript provides annotation like decorators:

@at.service(moduleName: string, serviceName: string)
@at.inject(dependencyOne: string, ...dependencies?: string[])
@at.component(moduleName: string, componentName: string)
@at.controller(moduleName: string, controllerName: string)
@at.directive(moduleName: string, directiveName: string)
@at.classFactory(moduleName: string, className: string)
@at.resource(moduleName: string, resourceClassName: string)

Why ?

Purpose of those decorators is to remove some ugly boilerplate from AngularJS applications written in TypeScript.

How ?

Service

Now one have to:

class SomeService {

    constructor() {
        // do stuff $http and $parse
    }
    
    public someMethod(anArg: number): boolean {
        // do some stuff
    }

}

angular.module('ngModuleName').service('someService', SomeService);

Using angular-typescript it will look like:

@service('ngModuleName', 'someService')
class SomeService {

    constructor() {
        // do stuff
    }
    
    public someMethod(anArg: number): boolean {
        // do some stuff
    }

}

Inject

@service('ngModuleName', 'someServiceName')
class SomeService {

    constructor(
        @inject('$http') $http: angular.IHttpService,
        @inject('$parse') private $$parse: angular.IParseService
    ) {
        // do stuff with $http and $$parse;
    }
    
    public someMethod(anArg: number): boolean {
        // do some stuff with this.$$parse
    }

}

or

@service('ngModuleName', 'someServiceName')
@inject('$http', '$parse')
class SomeService {

    constructor(
        $http: angular.IHttpService, 
        private $$parse: angular.IParseService
    ) {
        // do stuff with $http and $$parse;
    }
    
    public someMethod(anArg: number): boolean {
        // do some stuff with this.$$parse();
    }

}

Component

Static class members of component controller are used as component config object.

@component('ngModuleName', 'atSomeComponent')
class SomeComponentController {

    public static bindings: Object = {
      someBinding: '@'  
    };
    public static template: string = '<div><h1>{{ $ctrl.someBinding }}</h1></div>';
    // or
    public static templateUrl: string = './some-component.html';

    constructor(
        @inject('$scope') private $$scope: angular.IScope,
        @inject('$parse') private $$parse: angular.IParseService
    ) {
        // do stuff with $$scope and $$parse;
    }

}

Controller

@controller('ngModuleName', 'SomeController')
class SomeController {

    constructor(
        @inject('$scope') $scope: angular.IScope,
        @inject('$parse') private $$parse: angular.IParseService
    ) {
        // do stuff with $scope and $$parse;
    }
    
    public someMethod(anArg: number): boolean {
        // do some stuff with this.$$parse();
    }

}

Directive

Static class members of directive controller are used as config directive config.

@directive('ngModuleName', 'atSomeDirective')
class SomeDirectiveController {

    public static controllerAs: 'someDirectiveCtrl';
    public static templateUrl: string = '/partials/some-directive.html';
    public static link: angular.IDirectiveLinkFn = (scope, element, attrs, ctrl: SomeDirectiveController) => {
        ctrl.init(attrs.atSomeDirective);
    };

    constructor(
        @inject('$scope') private $$scope: angular.IScope,
        @inject('$parse') private $$parse: angular.IParseService
    ) {
        // do stuff with $$scope and $$parse;
    }
    
    public init(anArg: string): boolean {
        // do some stuff with this.$$parse and this.$$scope
    }

}

ClassFactory

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 '$$'.

@classFactory('test', 'Headers')
@inject('$http', '$parse')
class Headers {

    public accept: string;

    private $$http: angular.IHttpService;
    private $$parse: angular.IParseService;

    constructor() {
        this.accept = this.$$parse('defaults.headers.common.Accept')(this.$$http);
    }

}

and the somewhere else:

    
    constructor(
        @inject('Headers') Headers: Headers
    ) {
        this.headers = new Headers();
    }
    

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 (just like in @directive decorator).

@resource('test', 'UserResource')
@inject('$http', '$parse')
class UserResource extends at.Resource {

    public static url: string = '/fake/url';

    public name: string;
    public age: number;

    private $$http: angular.IHttpService;
    private $$parse: angular.IParseService;

    constructor(model?: ITestModel) {
        if (model) {
            this.name = model.name;
            this.age = model.age;
        }
    }

    public getLabel(): string {
        return `${ this.name }-${ String(this.age) }`;
    }

}

angular-typescript's People

Contributors

michalpanek avatar ulfryk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

angular-typescript's Issues

Rename library to angular-typescript-annotations

It would be better is this library has the name of angular-typescript-annotations or ng-ts-annotations. In that way users don't get confused thinking that this library is a wrapper or a rewriting of angular in typescript

use of private $$scope instead of $scope in class for Directive

I don't get it here, the injection of $scope and instead taking and making use of $$scope which is an internal implementation which is not supposed to be expose. or is it a typo or there is a reason for it?

@directive('ngModuleName', 'atSomeDirective')
class SomeDirectiveController {

public static controllerAs: 'someDirectiveCtrl';
public static templateUrl: string = '/partials/some-directive.html';
public static link: angular.IDirectiveLinkFn = (scope, element, attrs, ctrl: SomeDirectiveController) => {
    ctrl.init(attrs.atSomeDirective);
};

constructor(
    @inject('$scope') private $$scope: angular.IScope,
    @inject('$parse') private $$parse: angular.IParseService
) {
    // do stuff with $$scope and $$parse;
}

public init(anArg: string): boolean {
    // do some stuff with this.$$parse and this.$$scope
}

}

Use with typings

Is it possible to implement the use of this library through typings?
Or please give instructions on how to use this library in the project.

Provide .d.ts files

I'm using typings with jspm, I need to provide typings a path for the ambient declarations

Suggestion Directive Declaration

The idea from Angular 2

@Component({
  selector: "ot-site"
})
@View({
  templateUrl: "ot-site.html"
})

class OtSite() {
  constructor () {
  }

  // public methods here
}

I've modified this repository

https://github.com/nodeframe/angular-typescript

Modify to be

@at.service(module:string|angular.IModule, serviceName?: string)
@at.inject(dependencyOne: string, ...dependencies?: string[])
@at.controller(module: string|angular.IModule, controllerName?: string)
@at.directive(module: string|angular.IModule, directiveName?: string)
@at.classFactory(module: string|angular.IModule, className?: string)
@at.resource(module: string|angular.IModule, resourceClassName?: string)

if name is undefined, that use class name instead

example

@service('test')
class TestService {
  .....
}

and the somewhere else

    
    constructor(
        @inject('testService') TestService: TestService
    ) {
        this.testService = new TestService();
    }
    

Provide single entry point

There is no entry point for the package, consider doing what is being done at test/module.ts as entry point for the module

Usage of the resource decorator

Hey,

firstly, this repo is really great :)

Okay, this is more a question than an issue: Can you go a little bit deeper into the usage of resource decorators? I don't really get it.

Here are some problems i have:

  1. Custom actions are only supported for configuration, but there are no type definitions. Am I right?

    example:

    class SomeResource {
    
    static actions = { getByName: { ... } }
    
    }
    
    var resource = new SomeResource();
    resource.getByName() // would work in the native JS-world but TypeScript throws a compilation error
                         // because getByName doesn't exist on SomeResource
    
    

    I thought about using member decorators for custom actions like:

    
    @action(..)
    $getByName: (params: {name: string}) => ng.IPromise<Something>
    
    //  Another problem results from the naming conventions of static custom actions => `getByName`. 
    // But maybe it should be defined in an separate Interface like I mentioned on 2.
    
    

    Sure, another solution would be to create an Interface. But such an interface couldn't be implemented by the resource class (So very ugly: There is no connection between the class and the interface). Another issue would be, that you have to define a custom action on 3 different places (SomeResourceInstanceInterface, SomeResourceClassInterface and the configuration itself)

  2. In at.Resource there are non-static as well as static members defined. But when a resource is used it will look like this:

    @service('test', 'someService')
    @inject('SomeResource');
    class SomeService() {
    
    constructor(SomeResource: ???) {}
    
    }
    

    In my opinion it would make more sense to separate the static functions in an extra Interface (like SomeResourceClassInterface). What do you think? Because SomeResource should never be used directly without injecting it, the static members won't ever be used.

Thanks in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.