尝试使用Angular制作一个简易的待办事项应用
首先
这是《开源流Advent Calendar 2017》的最后一篇文章。
在我入职的第一年,我参与了一个使用Angular + Cordova制作的iOS应用的项目。在那时的培训期间,我创建了一个简单的TODO应用程序,所以为了复习,我打算再次使用Angular创建一个TODO应用程序。(请忽略太多技术性的讨论,请随意阅读。)
使用 Angular-Cli进行引入
我会安装Angular-Cli。
Angular-Cli是官方的命令行工具,只需要它,就可以轻松设置开发环境。
前项目是在Mac上进行的,但这次我将在自己的WindowsPC上进行创建。
我参考了以下链接来在Windows上进行安装。
- Windows環境でangular/cliを使えるようにする
安装Windows确实需要一些麻烦的步骤…我想要买台Mac。
创建原型
运行命令以创建 Angular 的模板应用程序。
$ ng new simple-todo-app --style=scss --routing

如果要运行应用程序,请输入以下命令。 您可以在浏览器中通过 localhost:4200 进行确认。
$ ng serve

ngx-bootstrap的引入
我想使用bootstrap来构建布局,所以我会引入ngx-bootstrap,利用它的指令来使用bootstrap的功能。
- Using with Bootstrap 4 with angular-cli
创建待办事项模块
我将创建一个模块来添加一个待办事项功能。
- まずは、angular-cli で todo 用の module、component の雛形を作成します。
// --routing オプションで routing.module.ts も同時に生成してくれます
$ ng generate module todo --routing
$ ng generate component todo/todo
通过执行上述命令,将自动生成src/app/todo以下的文件。如果要生成组件,则会自动将生成的组件附加到最近的module.ts文件中。

app.module.ts に todo.module.ts を追加します
import { TodoModule } from './todo/todo.module';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
TodoModule //<-- imports に追記
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
路由设置
设置路由以显示todoComponent的内容。
在 todo-routing.module.ts 文件中,我们可以将路由定义如下。这样一来,在 /todo 的路径上,就能跳转到 todoComponent 组件。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { TodoComponent } from './todo/todo.component';
// routes に path と component のペアを定義する
const routes: Routes = [
{ path: 'todo', component: TodoComponent }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class TodoRoutingModule { }
待办事项功能的实现
由于基础已经建立起来,接下来将实现待办事项功能。
-
- 今回はサーバー側は用意せずクライアント側でデータを保持するようにします。
サーバ側も構築してみたいですが、それは後々やりたいと思います。多分
一つのアイテムに 「タイトル」「詳細」「日時」 を入力できるようにします。
todoリストに対して、「完了/未完了」 の状態の切り替え および「削除」ができるようにします。
因为基础已经建立好了,所以接下来只需要在 todo.module.ts、todo.component.ts 和 todo.component.html 这三个文件中逐步添加即可。
定期任务.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { CollapseModule } from 'ngx-bootstrap/collapse';
import { AccordionModule } from 'ngx-bootstrap/accordion';
import { TodoRoutingModule } from './todo-routing.module';
import { TodoComponent } from './todo/todo.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
CollapseModule.forRoot(),
AccordionModule.forRoot(),
TodoRoutingModule
],
declarations: [TodoComponent]
})
export class TodoModule { }
只需要一个选项:只需在imports中添加FormModule和AccordionModule.forRoot()的4行代码。
模块和组件可以分别通过添加到imports和declarations来在该模块中使用添加的模块和组件的功能。
待办事项.component.ts
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
interface TodoItem {
title: string;
description: string;
isComplete: boolean;
date: any;
}
@Component({
selector: 'app-todo',
templateUrl: './todo.component.html',
styleUrls: ['./todo.component.scss']
})
export class TodoComponent implements OnInit {
// 詳細が表示されているか
public hasDetail = false;
// アイテムリスト
public itemList: Array<TodoItem> = new Array<TodoItem>();
// 入力フォーム
public todoForm: FormGroup;
constructor(
protected formBuilder: FormBuilder
) { }
ngOnInit() {
this.createForm();
}
createForm(): void {
// Form の作成と初期値設定をします。
this.todoForm = this.formBuilder.group({
title: ['',
[
Validators.required
]
],
description: [''],
date: [''],
isComplete: [false]
});
}
// todoItem を 保存します
onSaveTodoItem(): void {
const item: TodoItem = {
title: this.todoForm.get('title').value,
isComplete: false,
description: null,
date: null
};
if (this.hasDetail) {
item.description = this.todoForm.get('description').value;
item.date = this.todoForm.get('date').value;
}
this.itemList.push(item);
this.clearForm();
console.log(this.itemList);
}
// フォームの値をリセット
clearForm(): void {
this.todoForm.reset();
}
// 指定した要素を削除
onDeleteItem(index: number): void {
this.itemList.splice(index, 1);
}
}
由于本次功能比较简单,所以 component.ts 文件中的代码非常简洁。
在 createForm() 中,我们使用 ReactiveFormModule 的功能来生成一个 FormGroup 对象,以便统一管理输入表单。
FormGroup是一个非常方便的对象,可以用于获取输入的值、验证状态以及添加或删除表单项。
待办事项.component.html
<h1>Todo App</h1>
<form [formGroup]="todoForm">
<div class="form-group registItemArea">
<div class="input-group">
<input id="title" class="form-control" placeholder="Title" formControlName="title" />
<span class="input-group-btn">
<button class="btn btn-default" type="button" (click)="hasDetail = !hasDetail">詳細</button>
</span>
</div>
</div>
<div class="card card-block card-header" [collapse]="!hasDetail">
<div class="form-group">
<label for="description">
<strong>詳細:</strong>
</label>
<textarea id="text" class="form-control" formControlName="description"></textarea>
</div>
<div class="form-group">
<label for="date">
<strong>日付:</strong>
</label>
<input type="date" class="form-control" formControlName="date" />
</div>
</div>
</form>
<div class=" row ">
<div class="col-sm-2 ">
<button class="createBtn btn btn-success " [disabled]="this.todoForm.invalid" (click)="onSaveTodoItem()">作成</button>
</div>
</div>
<hr>
<div class="row itemListArea ">
<accordion class="col-sm-12">
<accordion-group *ngFor="let item of itemList; let i=index;">
<div accordion-heading [class.isComplete]="item.isComplete">
{{item.title}}
</div>
<div>
<strong>詳細:</strong>
<pre>{{item.description ? item.description : "-"}}</pre>
</div>
<div>
<strong>日付:</strong>
<span>{{item.date ? item.date : "-"}}</span>
</div>
<div>
<button class="btn btn-success" (click)="item.isComplete = !item.isComplete ">{{item.isComplete ? "未完了に戻す" : "完了にする"}}</button>
<button class="btn btn-danger" (click)="onDeleteItem(i)">削除</button>
</div>
</accordion-group>
</accordion>
</div>
我已经很久没用 Angular 来编写 HTML 了,但是模板语法真的非常方便呢。
只需要在 HTML 中编写简单的与页面显示相关的操作,所以真的很轻松。
本次使用的模板语法如下:
创建的待办事项应用程序

总结
-
- angular やっぱり楽しい
-
- angular-cli で大抵のことはやってくれるので環境構築が楽でした。(実際の案件ではいろいろ設定いじる必要があるとは思いますが。。。)
また、誰が作っても基本的に構成が同じになるので分かりやすいですね。
実装はロジックよりも bootstrap でレイアウト整えるのに時間がかかりました。。
关于未来
-
- サーバ側も用意して連携させたいです。
それに合わせて CURD 処理は service させる。今回はべた書きだったので><
DIが容易なのも angular の良いところだと思います。
編集など、機能もいろいろ追加したい
我希望将来能够实施并将此事项变成文章。
感谢您一直阅读到最后。