Todoアプリを見よう見真似で書いてみる。少しずつコードの抽象度を上げる練習をする。
Angularの要素について
- TypeScriptの構文について
- HTMLの構文について
- HTMLでToDoリストの外枠を書く
<section class="todoapp">
<header class="header">
<h1>todos</h1>
</header>
<section class="main">
<ul class="todo-list">
<li>
<div class="view">
todo1
</div>
</li>
<li>
<div class="view">
todo2
</div>
</li>
<li>
<div class="view">
todo3
</div>
</li>
</ul>
</section>
</section>
- データ部分をTypeScriptに移す
TypeScript側に変数を定義する
export class AppComponent {
todos = [
'todo1',
'todo2',
'todo3',
'todo4'
]
title = 'app';
}
HTML側で変数を利用する
<section class="main">
<ul class="todo-list">
<li *ngFor="let todo of todos">
<div class="view">{{todo}}</div>
</li>
</ul>
</section>
- データ部分をサービスに移譲する
新たなサービスを定義する
- サービスとはMVVMのモデルに該当する部分でデータソースやビジネスロジックの役割を担う
ng generate service todo
todoリストをサービス側に移譲する
import { Injectable } from '@angular/core';
@Injectable()
export class TodoService {
todos = []
constructor() {
this.todos = [
'todo1',
'todo2',
'todo3',
'todo4'
]
}
}
この時providersでの注入をわすれない
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [TodoService]
})
export class AppComponent {
service: TodoService
constructor(service: TodoService) {
this.service = service
}
}
HTMLはサービス側から値をとる
<li *ngFor="let todo of service.todos">
<div class="view">{{todo}}</div>
</li>
- Todoリストの追加
<header class="header">
<h1>todos</h1>
<input type="text" placeholder="new todo" [(ngModel)]="newTodo" (keyup.enter)="addTodo()">
</header>
addTodo() {
this.service.todos.push(this.newTodo)
this.newTodo = ''
}
- Todoリストの保存をする
AppComponent
addTodo() {
this.service.add(this.newTodo)
this.newTodo = ''
}
TodoService
add(todo: string) {
this.todos.push(todo)
this.updateStorage()
}
private updateStorage() {
localStorage.setItem('angular-todo', JSON.stringify(this.todos))
}
- TodoリストをlocalStorageから読み込む
constructor() {
this.todos = JSON.parse(localStorage.getItem('angular-todo') || '[]')
}
- Todoを型に変換する
export class Todo {
completed: Boolean;
title: String;
constructor(title: String) {
this.title = title
this.completed = false
}
}
add(title: string) {
this.todos.push(new Todo(title))
this.updateStorage()
}
<li *ngFor="let todo of service.todos; let index = index">
<div class="view">{{todo.title}}
<button (click)="deleteTodo(index)">delete</button>
</div>
</li>
- チェックボックスを追加する
<input class="toggle" type="checkbox" (click)="toggleCompletion(todo)" [checked]="todo.completed">
app.component.ts
toggleCompletion(todo: Todo) {
this.service.toggleCompletion(todo);
}
todo.service.ts
toggleCompletion(todo: Todo) {
todo.completed = !todo.completed
this.updateStorage()
}
- 状態に応じてクラスを付与する
<li *ngFor="let todo of service.todos" [class.completed]="todo.completed">
li.completed {
color: #d9d9d9;
text-decoration: line-through;
}