albatrosary's blog

UI/UXとエンタープライズシステム

Angular2 チュートリアル的な - AngularJS Advent Calendar 2015

Angular2のチュートリアルは何か無いかなということで"Try Angular 2"というのがありましたのでざっと見てみます。このエントリーは「AngularJS Advent Calendar 2015」12月2日の記事です。

Try Angular 2

これは"Angular Korea Meetup"の資料のようです。綺麗に解説されていますので内容を模写します(所謂コピペ的な)。

tryangular2.github.io

Project: TodoMVC

ここで使われているのがフロントエンドの定番TodoMVCです。これのAngular2版ということで。

github.com

全体的な構成

ES6 Modules

モジュールの読み込み

import {bootstrap, Component, View} from 'angular2/angular2';

ES6 Classes

function TodoAppとかTodoApp.prototype.activateとかで書いていたところ。

class TodoApp {}

@Component

selector<todo-app></todo-app>を指定

@Component({
  selector: 'todo-app’
})
class TodoApp {}

@View

Templateの指定

@Component({ ... })
@View({
  template: `<h1>{{title}}</h1>` // or:
  //templateUrl: 'todos.html'
})
class TodoApp { ... }

bootstrap(class)

ng-appとしたところ。

@Component({ selector: 'todo-app’ })
@View({ template: `<h1>{{title}}</h1>` })
class TodoApp {}

bootstrap(TodoApp);

Class Constructor

function TodoAppで書いていたところ。

@Component({ selector: 'todo-app’ })
class TodoApp {
  // initial values
  constructor() {
    this.todos = ['First thing', 'Second thing', 'Third thing'];
  }
}

Class Methods

TodoApp.prototype.activateとかで書いていたところ。

export class TodoStorage {
  // initial values
  constructor () {
    this.STORAGE_ID = 'todos-angular2';
  }

  // methods
  get() {
    return JSON.parse(localStorage.getItem(this.STORAGE_ID) || '[]');
  }
  put(todos) {
    localStorage.setItem(this.STORAGE_ID, JSON.stringify(todos));
  }
}

Inject Services

$injectだったところ。

import {TodoStorage} from 'todoStorageService';

@Component({
  selector: 'todo-app',
  injectables: [ TodoStorage ]
})
class TodoApp {
  constructor(storage: TodoStorage) {
    this.todos = storage.get() || [];
  }
}

Template Syntax

#Local Variables

<input #new-todo>

{{ binding }}

<input #new-todo />
<p>{{newTodo.value}}</p>

(event)="statement"

<input #new-todo (keydown)=“addTodo($event, newTodo.value)”>

ng-* => (event)

  • ng-click => (click)
  • ng-dblclick => (dblclick)
  • ng-keydown => (keydown)
  • ng-keyup => (keyup)
  • ng-mouseover => (mouseover)
  • ng-mouseenter => (mouseenter)
  • ng-mouseleave => (mouseleave)

[property]="expression"

<ul>
  <li [style.background-color]=“newTodo.value”>
    {{newTodo.value}}
  </li>
</ul>

ng-* => [property]

  • ng-src => [src]
  • ng-href => [href]
  • ng-show => [visible]
  • ng-hide => [hidden]
  • ng-style="color: red" => [style.color]="red"
  • ng-class="name" => [class.name]
  • ng-class={'name': condition} => [class.name]="condition"

Built-in Directives

ng-for

ディレクティブの宣言

import {bootstrap, Component, View, NgFor} from 'angular2/angular2';

@View({
  templateUrl: 'todos.html’,
  directives: [NgFor]
})
class TodoApp{
  constructor() {
    this.todos = [‘first thing’, ‘second thing’, ‘third thing’];
  }
}

ng-repeatで書いていたところはfor

*ng-for="#item of items"

 <ul *ng-for=“#todo of todos”>
  <li>
    <p>{{todo}}</p>
  </li>
</ul>

index

$indexで書いていたところ:

<ul *ng-for=“#todo of todos; var i = index;”>
  <li>
    <p>{{i}}. {{todo}}</p>
  </li>
</ul>

ng-If

ng-ifの宣言

import {bootstrap, Component, View, NgFor, NgIf} from 'angular2/angular2';

@View({
  templateUrl: 'todos.html’,
  directives: [NgFor, NgIf]
})

Class TodoApp{}

*ng-if="condition"

<ul *ng-for=“#todo of todos; var i = index;”>
  <li>
    <p>{{index}}. {{todo.title}}</p>
  </li>
  <form *ng-if="isEdit(i)">
    <p (dblclick)="doneEditing(todo)">Edit me!</p>
  </form>
</ul>

Angular 2 Forms

import {Control, FormDirectives, ControlDirective} from 'angular2/forms';

@Component({ ... })
@View({ ...
  directives: [NgFor, NgIf, FormDirectives]
})
class TodoApp {
  constructor( ...) {
    ...
    this.newTodo = new Control('');
  }
}

Control

<input [control]="newTodo" (keydown)="addTodo($event)">

Validators

import {CustomValidators} from 'validators';

@Component({
  injectables: [TodoStorage, CustomValidators]
})
class TodoApp{
  constructor(storage: TodoStorage, custom: CustomValidators) {
    this.newTodo = new Control('', custom.badLanguage);
  }
}

Custom Validators

export class CustomValidators{
  // c: Control
  badLanguage(c) {
  // 18dogbaby = bad language in Korean
  if(c.value.match(/18dogbaby/)) {
    return {
      badLanguage: true
    };
  }
  // return null = valid
  return null;
  }
}

Validators

<form id="todo-form" [class.invalid]="!newTodo.valid">

最後に

Angular1を理解していればAngular2に移行するのはそれほど難しくないかな。中身はまったく別物のようだけど。Angular2はまだベータ版にもなってないアルファ版なので遊びで使うくらい。