跳到主要內容

AngularJS TodoList

再來的第二個教學就是很多人熟知的Todo List,因為Todo List 包含了CRUD這幾個主要功能
• 讀取:   列出todos所有項目、查看總筆數與Todo 項目、搜尋某筆項目
• 新增:新增一個todo項目。
• 修改:修改特定todo項目。
• 刪除:刪除特定項目、刪除已完成的todo項目。

資料結構

將todo list存在陣列中,每個todo項目有欄位text、done
• text:內文。
• done:是否完成。

印出所有項目

在<li>元素上加入了AngularJS的迭代器ng-repeat,然後用"todo in todos"的語法,從todos這個陣列清單中,取出一個個的物件,指派給todo ,然後在span裡列印出item.text 並且當點選的時候,可以將該項目加上刪除線。

html
<li ng-repeat="todo in todos >
<input type="checkbox" ng-model="todo.done" />
<span class="done-{{todo.done}}" ng-dblclick="edit(todo)">{{todo.text}}</span>
</li>

css
.done-true{
text-decoration: line-through;
color:grey
}


Ng-repeat 官方說明


除此之外,使用了function getTotalTodos 計算每次新增刪除後的todo總數
html
<h2>Total todos: {{getTotalTodos()}}</h2>
js
$scope.getTotalTodos = function () {
return $scope.todos.length;
};


搜尋

在搜尋列中,我們利用 ng-model="searchInput" 綁定 <input>,然後將每個會被重複的todo item區塊標註filter而能依照searchInput的值做篩選。

html

<input type="text" placeholder="Search for..." ng-model="searchInput">
此外修改ng-repeat
<li ng-repeat="todo in todos >
<input type="checkbox" ng-model="todo.done" />
<span class="done-{{todo.done}}" ng-dblclick="edit(todo)">{{todo.text}}</span>
</li>

新增

該功能是一個輸入框與一個按鈕,輸入一些文字後按下Add按鈕,即可新增新的項目。
透過ng-model="formTodoText"綁定這個<input>,然後利用 ng-click監聽Add按鈕的click事件,當按下這個按鈕時,執行addITodo()這個function。

html
<form class="form-horizontal">
<input type="text" ng-model="formTodoText" ng-model-instant>
<button ng-click="addTodo()">
<i class="icon-plus">Add</button>
</form>

js
$scope.addTodo = function () {
$scope.todos.push({ text: $scope.formTodoText, done: false });
$scope.formTodoText = '';
};

html執行於addTodo的function後,該function會抓取當下formTodoText的值並且塞進todos陣列中,之後清空 formTodoText

修改

該功能要觸發時,先要點擊需要修改的項目,變成可編輯後,即可修改該值

1.進入編輯模式:利用ng-dblclick指令,在double click的時後,用”edit(item)”來進入編輯模式。
2.結束編輯模式:利用按下儲存按鈕時,ng-click觸發”save(item)”,來結束編輯模式。

html
<div ng-hide="todo.editing">
<input type="checkbox" ng-model="todo.done" />
<span class="done-{{todo.done}}" ng-dblclick="edit(todo)">{{todo.text}}</span>
<button type="button" ng-click="remove(todo)">Remove</button>
</div>
<div ng-show="todo.editing">
<input ng-model="todo.text">
<button ng-click="save(todo)">儲存</button>
</div>

js
$scope.edit = function(item){
    item.editing = true;
}
$scope.save = function(item){
    delete item.editing;
}



新增edit和save兩個function,edit function其實是在item加上editing的屬值,並給它true的值,一旦賦值之後,因為資料狀態異動,外觀的ng-show、ng-hide馬上會被觸發,於是原本的待辦事項就會隱藏,而待辦事項編輯框就會出現。
save函式作的則是相反的動作,編輯完成後,我們不需要editing這個多餘的屬性來干擾原來的資料結構,於是就用javascript的delete的語法,刪去item物件的editing屬性。這樣一來ng-show和ng-hide會再偵測到資料異動,於是狀態又會回復成原來的狀態。



刪除

在刪除功能中,一個是指定某個項目刪除,而另一個則是指定已完成的項目刪除

刪除某項目

使用ng-click="remove(todo)綁在按鈕「Remove」上,當按下「Remove」時觸發remove(),並將該項目物件傳入該function。
html
<button type="button" ng-click="remove(todo)">Remove</button>


js
$scope.remove = function (item) {
var index = $scope.todos.indexOf(item);
$scope.todos.splice(index, 1);
};


Remove function則利用 indexOf去找當下item位於todos陣列的哪一個位置,之後用splice刪除該項目

indexOf的用法

Splice 的用法

刪除已完成的項目
使用ng-click="clearCompleted綁在按鈕「Remove」上,當按下「Remove」時觸發remove()


html
<button ng-click="clearCompleted()">clean completed</button>


js
$scope.clearCompleted = function () {
var oldTodos = $scope.todos;
$scope.todos = [];
angular.forEach(oldTodos, function (todo) {
if (!todo.done) $scope.todos.push(todo);
});
};

clearCompleted function先暫存當下todos 陣列中所有的值於oldTodos中,清空原有的todos陣列後,針對oldTodos中的每一筆,當該筆done為false時,則將該筆push至原本的todos中

DEMO

以下是完成品

留言