typescript 双向绑定

双向绑定

two-way-binding.component.ts
import {Component} from '@angular/core';

@Component({
    selector: "two-way-binding",
    template: `
        <!-- Main component for a primary marketing message or call to action -->
        <div class="jumbotron">
            <h1>{{ title.title }}</h1>
            <p>{{ title.description }}</p>
            <p>Two Way Bidnig : {{ twoWay }}</p>
            
            <input type="text" [(ngModel)]="twoWay"><input type="button" value="Reset" (click)="twoWay='' ">


            
        </div>


        
        `
})

export class TwoWayBindingComponent {
    isActive = false;

    twoWay = "Hello Gagu";

    title = {
        title: "Two Way Binding",
        description: "Two Way Binding in angular 2."
    }

}

typescript 类结合

类结合

class-binding.component.ts
import {Component} from '@angular/core';

@Component({
    selector: "style-binding",
    template: `
        <!-- Main component for a primary marketing message or call to action -->
        <div class="jumbotron">
            <h1>{{ title.title }}</h1>
            <p>{{ title.description }}</p>
            <p>IsActive : {{ isActive }}</p>
            <input type="button" value="Hello Gugu..." [class]="isActive ? 'btn btn-success' : 'btn btn-primary' " (click)="clickMe()">
            
        </div>


        
        `
})

export class ClassBindingComponent {
    isActive = false;

    title = {
        title: "Class Binding",
        description: "Class Binding in angular 2. Click on button to bind style"
    }

    clickMe() {
        this.isActive = true;
    }
}

typescript 风格结合

风格结合

style-binding.component.ts
import {Component} from '@angular/core';

@Component({
    selector: "style-binding",
    template: `
        <!-- Main component for a primary marketing message or call to action -->
        <div class="jumbotron">
            <h1>{{ title.title }}</h1>
            <p>{{ title.description }}</p>
            <p>IsActive : {{ isActive }}</p>
            <input type="button" value="Register Here" [style.backgroundColor]="isActive ? 'blue' : 'gray' " (click)="clickMe()">
            
        </div>


        
        `
})

export class StyleBindingComponent {
    isActive = false;

    title = {
        title: "Style Binding",
        description: "Style Binding in angular 2. Click on button to bind style"
    }

    clickMe() {
        this.isActive = true;
    }
}

typescript 指令

指令

courses.directive.html
<!-- Main component for a primary marketing message or call to action -->
      <div class="jumbotron">
        <h1>{{ tilte.title }}</h1>
        <p>{{ tilte.description }}</p>

    
        <form class="form-signin">
            <h2 class="form-signin-heading">Please sign in</h2>
            <label for="inputEmail" class="sr-only">Email address</label>
            <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus autoGrow>
            <br>
            <label for="inputPassword" class="sr-only">Password</label>
            <input type="password" id="inputPassword" class="form-control" placeholder="Password" required autoGrow>
            <br>
            <button class="btn btn-lg btn-primary btn-block" type="submit" disabled>Sign in</button>
      </form>
      </div>

auto-grow.directive.ts
import { Directive, ElementRef, Renderer } from '@angular/core';

@Directive({
    selector: '[autoGrow]',
    host: {
        '(focus)': 'onFocus()',
        '(blur)': 'onBlur()'
    }
})

export class AutoGrowDirective {

    constructor(private el:ElementRef, private renderer: Renderer) {}
    
    onFocus() {
        this.renderer.setElementStyle(this.el.nativeElement, 'width', '300');
    }

    onBlur() {
        this.renderer.setElementStyle(this.el.nativeElement, 'width', '500');
    }

}
auto-grow.component.ts
import {Component} from '@angular/core';

import {AutoGrowDirective} from './auto-grow.directive';

@Component({
    selector: "directives",
    templateUrl: "app/directives/views/courses.directive.html",
    directives: [AutoGrowDirective]
})

export class AutoGrowComponent {
    tilte = {
        title: "Directives",
        description: "Directives in Angular 2, Auto Grow directive, when user will focus or blur from input then width of input automatic increased decreased"
    }
}

typescript 服务棱角

服务棱角

courses.services.html
<!-- Main component for a primary marketing message or call to action -->
      <div class="jumbotron">
        <h1>{{ tilte.title }}</h1>
        <p>{{ tilte.description }}</p>

    
        <table class="table">
          <tr>
            <th>Course Name</th>
            <th>Vote</th>
            <th>Open Source</th>
          </tr>
          <tr *ngFor="let loopdata of courses">
            <td>{{ loopdata.courseName }}</td>
            <td>{{ loopdata.openSource }}</td>
            <td>{{ loopdata.vote }}</td>
          </tr>

        </table>

      </div>

courses.service.ts
export class CoursesService {
    getCourses() {
        return [
            {
                courseName: "PHP",
                vote: "80%",
                openSource: "yes"
            },
            {
                courseName: "Angular 2",
                vote: "100%",
                openSource: "yes"
            },
            {
                courseName: "Swift Language",
                vote: "70%",
                openSource: "no"
            },
            {
                courseName: ".Net",
                vote: "80%",
                openSource: "no"
            }    
        ]
    }
}
course-services.component.ts
import {Component} from '@angular/core';

import {CoursesService} from './courses.service';

@Component({
    selector: "services-angular",
    templateUrl: "app/services/views/courses.services.html",
    providers: [CoursesService]
})

export class CourseServicesComponent {
    tilte = {
        title: "Services",
        description: "Services in Angular 2"
    }

    courses;

    constructor(coursesService: CoursesService) {
        this.courses = coursesService.getCourses();
        console.log(this.courses);
    }
}

typescript 基础数据渲染

基础数据渲染

basic.component.ts
import {Component} from '@angular/core';

@Component({
    selector: "basics-data-rendering",
    templateUrl: "app/basics/views/basic.component.html"
})

export class BasicComponent {

    data = {
        title: "Basic Data Rendering",
        description: "This is expamle of basic data rendering"
    }

}

typescript Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming/angular-2/

Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming/angular-2/

app-3-router.spec.ts
import {
  beforeEachProviders,
  describe,
  expect,
  inject,
  it,
} from '@angular/core/testing';
import { 
  ComponentFixture, 
  TestComponentBuilder,
} from '@angular/compiler/testing';
import { ROUTER_FAKE_PROVIDERS } from '@angular/router/testing';
import { App } from './app';

import { setBaseTestProviders } from '@angular/core/testing';
import {
  TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,
  TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
} from '@angular/platform-browser-dynamic/testing';

setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);

describe('App', () => {

  beforeEachProviders(() => [ROUTER_FAKE_PROVIDERS])

  it('should be able to test', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
    return tcb.createAsync(App).then(componentFixture => {
      componentFixture.detectChanges();
      expect(true).toBe(true);
    });
  }));

});
app-3-http.spec.ts
// App
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class TestService {
  constructor(private http: Http) {}

  getUsers() {
    return this.http.get('http://foo.bar');
  }
}


// App tests
import {
  beforeEach,
  beforeEachProviders,
  describe,
  expect,
  inject,
  it,
} from '@angular/core/testing';

import { provide } from '@angular/core';
import { BaseRequestOptions, Response, ResponseOptions } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';

describe('Http', () => {

  beforeEachProviders(() => [
    TestService,
    BaseRequestOptions,
    MockBackend,
    provide(Http, {
      useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
        return new Http(backend, defaultOptions);
      },
      deps: [MockBackend, BaseRequestOptions]
    })
  ]);

  beforeEach(inject([MockBackend], (backend: MockBackend) => {
    const baseResponse = new Response(new ResponseOptions({ body: 'got response' }));
    backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
  }));

  it('should return response when subscribed to getUsers',
    inject([TestService], (testService: TestService) => {
      testService.getUsers().subscribe((res: Response) => {
        expect(res.text()).toBe('got response');
      });
    })
  );

})
app-2-services.spec.ts
// App
class TestService {
  public name: string = 'Injected Service';
}


// App tests
import {
  it,
  describe,
  expect,
  inject,
  beforeEachProviders,
} from '@angular/core/testing';

import { provide } from '@angular/core';
import { setBaseTestProviders } from '@angular/core/testing';
import {
  TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,
  TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
} from '@angular/platform-browser-dynamic/testing';

setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);


describe('TestService', () => {

  beforeEach(() => {
    this.testService = new TestService();
  });

  it('should have name property set', () => {
    expect(this.testService.name).toBe('Injected Service');
  });

});


describe('TestService Injected', () => {

  beforeEachProviders(() => [TestService]);

  it('should have name property set', inject([TestService], (testService: TestService) => {
    expect(testService.name).toBe('Injected Service');
  }));

});


class MockTestService {
  public mockName: string = 'Mocked Service';
}

describe('TestService Mocked', () => {

  beforeEachProviders(() => [
    provide(TestService, {useClass: MockTestService})
  ]);

  it('should have name property set', inject([TestService], (testService: TestService) => {
    expect(testService.mockName).toBe('Mocked Service');
  }));

});


class MockTestServiceInherited extends TestService {
  public sayHello(): string {
    return this.name;
  }
}

describe('TestService Mocked Inherited', () => {

  beforeEachProviders(() => [
    provide(TestService, { useClass: MockTestServiceInherited })
  ]);

  it('should say hello with name', inject([TestService], (testService: TestService) => {
    expect(testService.sayHello()).toBe('Injected Service');
  }));

});
app-2-components.spec.ts
// App
import { Component, Input } from '@angular/core';
import { NgFor } from '@angular/common';

@Component({
  selector: 'list',
  template: '<span *ngFor="let user of users">{{ user }}</span>',
  directives: [NgFor],
})
export class ListComponent {
  @Input() public users: Array<string> = [];
}


// App tests
import {
  async,
  it,
  describe,
  expect,
  inject,
  beforeEach,
  beforeEachProviders,
} from '@angular/core/testing';

import {
  ComponentFixture,
  TestComponentBuilder,
} from '@angular/compiler/testing'

import { setBaseTestProviders } from '@angular/core/testing';
import {
  TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,
  TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
} from '@angular/platform-browser-dynamic/testing';

setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);


describe('ListComponent', () => {

  it('should render list', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
    return tcb.createAsync(ListComponent).then(componentFixture => {
      const element = componentFixture.nativeElement;
      componentFixture.componentInstance.users = ['John'];
      componentFixture.detectChanges();
      expect(element.querySelectorAll('span').length).toBe(1);
    });
  }));

});



// App DI
class UserService {
  public users: Array<string> = ['John'];
}

@Component({
  selector: 'list',
  template: '<span *ngFor="let user of users">{{ user }}</span>',
  directives: [NgFor],
})
class ListComponentBootstrapDI {
  private users: Array<string> = [];

  constructor(userService: UserService) {
    this.users = userService.users;
  }
}


// App DI tests
import { provide } from '@angular/core';

class MockUserService {
  public users: Array<string> = ['John', 'Steve'];
}

describe('ListComponent DI', () => {

  beforeEachProviders(() => [
    provide(UserService, { useClass: MockUserService })
  ]);

  it('should render list', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
    return tcb.createAsync(ListComponentBootstrapDI).then(componentFixture => {
      const element = componentFixture.nativeElement;
      componentFixture.detectChanges();
      expect(element.querySelectorAll('span').length).toBe(2);
    });
  }));

});


// App DI for Component
@Component({
  selector: 'list',
  template: '<span *ngFor="let user of users">{{ user }}</span>',
  directives: [NgFor],
  providers: [UserService],
})
class ListComponentComponentDI {
  private users: Array<string> = [];

  constructor(userService: UserService) {
    this.users = userService.users;
  }
}

// App DI for Component tests
describe('ListComponent DI Component', () => {
  it('should render list', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
    tcb
      .overrideProviders(
        ListComponentComponentDI,
        [provide(UserService, { useClass: MockUserService })]
      )
      .createAsync(ListComponentComponentDI).then(componentFixture => {
      const element = componentFixture.nativeElement;
      componentFixture.detectChanges();
      expect(element.querySelectorAll('span').length).toBe(2);
    });
  }));
});



// App final test
describe('ListComponent Final', () => {

  beforeEach(async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
    tcb
      .overrideProviders(
        ListComponentComponentDI,
        [provide(UserService, { useClass: MockUserService })]
      )
      .createAsync(ListComponentComponentDI)
      .then(componentFixture => {
        this.listComponentFixture = componentFixture;
      });
  })));

  it('should render list', () => {
    const element = this.listComponentFixture.nativeElement;
    this.listComponentFixture.detectChanges();
    expect(element.querySelectorAll('span').length).toBe(2);
  });

});
app-1.spec.ts
// App
import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: '<span>{{ sayHello() }}</span>',
})
export class App {
  public name: string = 'John';

  sayHello(): string {
    return `Hello ${this.name}`;
  }
}


// App tests

describe('App', () => {

  beforeEach(() => {
    this.app = new App();
  });

  it('should have name property', () => {
    expect(this.app.name).toBe('John');
  });

  it('should say hello with name property', () => {
    expect(this.app.sayHello()).toBe('Hello John');
  });

});

typescript 枚举允许我们定义一组命名的数字常量。可以使用enum关键字定义枚举。 <br/> http://www.typescriptlang.org/docs

枚举允许我们定义一组命名的数字常量。可以使用enum关键字定义枚举。 <br/> http://www.typescriptlang.org/docs/handbook/enums.html

enums2.ts
enum Tristate {
    False,
    True,
    Unknown
}
console.log(Tristate[0]); // "False"
console.log(Tristate["False"]); // 0
console.log(Tristate[Tristate.False]); // "False" because `Tristate.False == 0`
enums.ts
enum Direction {
    Up = 1,
    Down,
    Left,
    Right
}
enum Color {
    DarkRed = 3,  // 3
    DarkGreen,    // 4
    DarkBlue      // 5
}
/*
The body of an enum consists of zero or more enum members. Enum members have numeric value associated with them and can be either constant or computed. An enum member is considered constant if:

It does not have an initializer and the preceding enum member was constant. In this case the value of the current enum member will be the value of the preceding enum member plus one. One exception to this rule is the first element on an enum. If it does not have initializer it is assigned the value 0.
The enum member is initialized with a constant enum expression. A constant enum expression is a subset of TypeScript expressions that can be fully evaluated at compile time. An expression is a constant enum expression if it is either:
numeric literal
reference to previously defined constant enum member (it can be defined in different enum). If member is defined in the same enum it can be referenced using unqualified name.
parenthesized constant enum expression
+, -, ~ unary operators applied to constant enum expression
+, -, *, /, %, <<, >>, >>>, &, |, ^ binary operators with constant enum expressions as operands It is a compile time error for constant enum expressions to be evaluated to NaN or Infinity.
 * /

typescript 使用接口定义自定义类型。 <br/>接口是一种告诉TypeScript有关对象的信息的方法,可以帮助您在bui中捕获更多错误

使用接口定义自定义类型。 <br/>接口是一种告诉TypeScript有关对象的信息的方法,可以帮助您在构建时捕获更多错误,但不要依赖它们在运行时存在。

custom_types_with_interfaces.ts
interface Todo {
    name: string;
    completed?: boolean; //What this does is tells TypeScript not every Todo object needs to have a completed property in order to be a Todo. But, when it does have the completed property, that property needs to always be a boolean value.
}

interface ITodoService {
    add(todo: Todo): Todo;
    delete(todo: Todo): void;
    getAll(): Todo[];
    getById(todoId: number): Todo;
}

var todo: Todo = {
    name: "Pick up drycleaning"
};

typescript 功能过载

功能过载

function_overloads.ts
function totalLength(x: string, y: string): number
function totalLength(x: any[], y: any[]): number
function totalLength(x: (string | any[]), y: (string | any[])): number {
    var total: number = x.length + y.length;
    
    x.slice(0)
    
    if(x instanceof Array) {
        x.push('TypeScript')
    }
    
    if(x instanceof String) {
        x.substr(0)
    }
    
    return total;
}

totalLength()