5 things to know if you want to use Angular4(Angular2) with CoffeeScript

Are you tired to type many comma and braces? Don't worry, We can use CoffeeScript super simple syntax for Angular2(Angular4).

This described things you have to know when you migrate TypeScript to CoffeeScript.

Importing

//TypeScript
import { Component } from '@angular/core';
#CoffeeScript
{ Component } =require '@angular/core'

Decorator

//TypeScript
@Component({
  selector: 'my-app',
  template: `
    <h1>{{title}}</h1>
  `
})
export class AppComponent {
  title = 'Tour of Heroes';
}

in CoffeeScript, es-decorate module make it possible to use TypeScript's decorator(@)

like this.

#CoffeeScript
decorate=require "es-decorate"
AppComponent=decorate [
    Component
        selector:'my-app'
        template:"""
            <h1>{{title}}</h1>
        """
],class
    title:'Tour of Heroes'

1st argument is array of decorators. 2nd argument is target class. CofffeeScript supports unnamed class. Just assign to decorated class name. like above.

I like _(underbar) for short hand.

//CoffeeScript
_=require "es-decorate"
AppComponent=_ [
    Component
        selector:'my-app'
        template:"""
            <h1>{{title}}</h1>
        """
],class
    title:'Tour of Heroes'

Don't you think this is not so longer than TypeScript?

Dependency Injection(DI)

//TypeScript
@Injectable()
export class HeroService {
  getHero():String {
    return("The hero");
}

@Component({
  selector: 'my-app',
  template: `
    <h1>{{heroService.getHero()}}</h1>
  `,
  providers:[HeroService]
})
export class AppComponent {
  constructor(private heroService: HeroService){}
}

Since of Angular2's Dependency Injection(DI) knows constructor's parameter by TypeScript's metadata.

TypeScript embed metadata automatically by decorator.

@__metadata("design:type", HeroService)

Another option is Parameter Decorator. Parameter Decorator is a sort of class decorator which receives parameter index number.

You can tell constructor's parameter's kind by Parameter Decorator instead of metadata to Angular

We use a snippet below to use Parameter Decorator on CoffeeScript.

_=require "es-decorate"
_P=(index,decorator)->(target,key)->decorator(target,key,index)
_I=(index,provider)->_P index,Inject(provider)

By this snippet, CoffeeScript version of DI has been like below.

//CoffeeScript
HeroService=_ [
    Injectable()
],class
    getHero:->"The hero"

AppCommponent=_ [
    Component
        selector:'my-app'
        template:"""
            <h1>{{heroService.getHero()}}</h1>
        """
        providers:[HeroService]
        _I 0,HeroService
],class
    constructor(@heroService):->

Look at "_I 0,HeroService", This tells "Parameter 0 of constructor is HeroService" to Angular.

Parameter Decorator

As mentioned last section, Parameter Decorator is just a sort of class decorator.

//TypeScript
@someDecorator
export class SomeClass {

This class decorator will be converted by TypeScript transpiler like this.

//JS
SomeClass=someDecorator(SomeClass);

When using Parameter Decorator,

//TypeScript
export class SomeClass {
    constructor(@Inject(SomeService) someService:SomeService){}

will be

//JS
SomeClass=__param(0,Inject(SomeClass))(SomeClass);

__param() generates class decorator from 2nd parameter's decorator which bound 1st parameter's index number.

Look at the CoffeeScript snippet of last section

_P=(index,decorator)->(target,key)->decorator(target,key,index)
_I=(index,provider)->_P index,Inject(provider)

_P is generic Parameter Decorator. Same as __param() in TypeScript above for generating class decorator from parameter decorator.

_I is shorthand to tell constructor's parameter's kind to Angular by Inject decorator.

Member Decorator

Do you want to access DOM element from Angular's component? You should know about Member Decorator.

//TypeScript
@Component({
  selector: 'my-app',
  template: `
    <input #box type='text' value='hero'></input>
  `
})
export class AppComponent {
    @ViewChild('box') elem:ElementRef;
    someMethod() {
        elem.nativeElement.value='super hero';
    }
}

You can access via elem property to DOM element.

@ViewChild is Member Decorator. Member Decorator is a sort of Method Decorator. Method Decorator's implementation is like below.

//JS
Object.defineProperty(prototype, name, decorator(prototype, name, descriptor));

Yes, method decorator is just changing descriptor.

Lets back to ViewChild. @ViewChild('box') elem:ElementRef; is calling ViewChild('box') with elem's prototype,name,descriptor.

CoffeeScript's snippet is here.

//CoffeeScript
_M=(decorator,id,self)->_(id,self,decorator,null)
_VIEWCHILD=(id,self)->_M(ViewChild(id),id,self)

_M is generic member decorator helper. Use _VIEWCHILD to access DOM element like this

AppCommponent=_ [
    Component
        selector:'my-app'
        template:"""
            <input #box type='text' value='hero'></input>
        """
],class
    _VIEWCHILD 'box',@
    someMethod:->
        @box.nativeElement.value='super hero';

@Input/@Output decorators are also method decorator. here is example

//CoffeeScript
_M=(decorator,id,self)->_(id,self,decorator,null)
_INPUT=(id,self)->_M(Input(),id,self)
_OUTPUT=(id,self)->_M(Output(),id,self)
AppCommponent=_ [
    Component
        selector:'my-element'
        template:"""
            <input type='text' [value]='hero'></input>
        """
],class
    _INPUT 'hero',@

//Use like '<my-element [hero]="super hero"></my-element>'
AppCommponent=_ [
    Component
        selector:'my-element'
        template:"""
            <div  [click]='onClick()'>Click me</div>
        """
],class
    _OUTPUT 'hero',@

    constructor:->
        @hero=new EventEmitter()

    onClick:->
        @hero.emit()

//Use like '<my-element (hero)="onHero()"></my-element>'

Popular Articles from This Page

Top Page

Economizing Technology > 5 things to know if you want to use Angular4(Angular2) with CoffeeScript