iT邦幫忙

9

邊學AngularJS邊做Todo List (3) - Todo List 刪項目

上一回我們用AngularJS完成最基本的加入項目功能,而就Todo List來說,當然有加入,就要有刪除,才能知道事情做完了。

這回的刪除功能,借助AngularJS的力量,我們一樣不用寫太多code。

我們會在controllers.js新增一個TodoCrtlRemovable的function,它其實是上回TodoCrtl加上移除的功能而已,之所以要另啟一個function來做,只是為了說明與對照上的方便,就實務上,把新加入的功能放進TodoCrtl中就可以了。

這回刪除的功能,主角是Filter

就AngularJS的模板(template)設計哲學來說,它非常強調像是條件式、迴圈這些東西,應該是屬於Controller的範圍,模板上不應該看見它。但模板上有時有非得有這些東西,這時AngularJS就會提供一些工具來協助。例如上次看到的ng-repeat,以及我們這次要談的Filter
【模版加入刪除的機制】

照例,先來看我們的html檔,我們把上次的檔案複製一份,重新命名為todoWithRemove.html,然後改寫內容如下。

<html ng-app>
  
    <meta charset="utf-8">  
    <title>邊學AngularJS邊做Todo List (3)</title>
    <script type="text/javascript" src="http://code.angularjs.org/angular-1.0.1.min.js"></script>
    <script type="text/javascript" src="js/controllers.js"></script>
  
  <body ng-controller="TodoCrtlRemovable">
      <h1>Todo List</h1>
      <form ng-submit="addItem()">
        <input type="text" ng-model="newItem" name="newItem" />
        <input type="submit" id="submit" value="新增待辦事項" />
      </form>
      <ul id="todo">
        <li ng-repeat="item in todoList | filter:{isFinish:false}">
          <input type="checkbox" ng-click="removeItem(item)">
          {{item.label }}
        </li>
      </ul>

      <hr>

      <h1>Finished!</h1>  
      <ul id="finish">
        <li ng-repeat="item in todoList | filter:{isFinish:true}">
          {{item.label}}
        </li>
      </ul>
  

完成後的樣子應該是如此:

首先我們把ng-cotroller對應到TodoCrtlRemovable,剛剛說過,我們會在這個controller加上刪除的功能。

  <body ng-controller="TodoCrtlRemovable">

<ul>的部分,現在變成兩個,一個是上次完成的待辦事項清單,我們加上了id#todo識別。

另一個id#finish,則是我們準備用來放置已經完成工作的事情。

這兩個<ul>基本上結構一樣,只有下列幾個地方不同

(1) #todo與#finish都有一個物件當filter參數,只是參數的值不同。當isFinish標示為false時,表示尚未完成,標示為true則表示已完成。

(2) #todo多了一行:

<input type="checkbox" ng-click="removeItem(item)">

這是我們為辦待事項增加一個核取方塊,當核取方塊點擊時,ng-click這個指令就會監聽到,進而執行刪除的動作(執行removeItem這個事件處理器,參數則是代表自己的item)。

模板的部分,只要加入這些東西就完成刪除工作的所需要的動作。

很容易理解吧。

【Filter究竟是什麼?】

AngularJS提供了一系列的Filter,讓開發者可以用來清理資料,例如:lowercase、uppercase、orderBy、currency、date,這些filter大概都可以望文生義,是用來清理諸如文字大小寫轉換、排序、貨幣、日期等。

舉例來說,{{ ‘HELLO’ | lowercase }} 的結果,就是會變成 ‘hello’。

filter的基本用法就是像上面這樣{{ expression | filter }}

另外filter後面有的可以接參數,例如

{{ 3.1415926 | number:2 }}

輸出結果就會是 3.14。

而我們所使用的filter則是一個通用型的過濾器,你可以指定字串物件函式給它當過濾條件。以我們的例子來說,我們提供一個物件,裡面的過濾條件就是isFinish的值。這樣的設計,相當直觀易懂。

因此當todoList這個陣列在取出待辦事項時,#todo只會列出isFinish為false的部分。相對的,#finish則只會取出isFinish為true的事項。

關於filter更詳細的介紹,可以參考:http://docs.angularjs.org/api/ng.filter:filter

【刪除的Controller】

比起Layout,Controller要動的地方更少。

Controller的程式碼如下:

function TodoCrtlRemovable($scope) {
  $scope.newItem = '';
  $scope.todoList = [];
  $scope.addItem = function(){
    if(this.newItem){
       this.todoList.push({label:this.newItem,isFinish:false});
       this.newItem = '';
    }
  }
  $scope.removeItem = function(item){
      item.isFinish = true;
  }
}

在原本addItem的函式中,我們替待辦事項加上isFinish這個屬性,預設值是false,因為剛新加上的事情,就是還沒做的狀態。

this.todoList.push({label:this.newItem,isFinish:false});

另外,我們要寫removeItem這個函式,來為我們刪去完成的項目,這個函式的寫法,就是把變動的項目當參數傳入,然後改寫它的isFinish的值而已。

 $scope.removeItem = function(item){
     item.isFinish = true;
  }

由於我們把刪除的點擊核取方塊動作和removeItem綁定,因此只要點擊待辦事項的核取方塊,它的isFinish狀態就會被設成true。歸功於AngularJS雙向資料綁定的特性,只要你的model值有異動,view也會跟著改變。換句話說,我們只是把isFinish的值改為true,AngularJS就會幫我們把完成的事項拉到下面的完成列表中。

就這樣,刪除的功能寫完了。

現在你可以去打開todoWithRemove.html來玩一下,完成的樣子應該就是如此。

沒體驗過之前,你是不能感受有多神奇的啊。

Live Demo ::完整的程式碼


邊學AngularJS邊做Todo List (1) - Hello World
邊學AngularJS邊做Todo List (2) - Todo List 動起來
邊學AngularJS邊做Todo List (3) - Todo List 刪項目
邊學AngularJS邊做Todo List (4) - 修改待辦事項
邊學AngularJS邊做Todo List (5) - 為測試作準備
邊學AngularJS邊做Todo List (6) - E2E測試(上)


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
ted99tw
iT邦高手 1 級 ‧ 2012-07-20 08:40:42

灑花加油!灑花

0
wordsmith
iT邦高手 1 級 ‧ 2012-07-20 13:17:17

寫得不錯,學習了~

0
zbrong
iT邦新手 5 級 ‧ 2013-04-24 10:46:40

楼主啊,你这里实际上是修改,而不是删除。仅仅是修改了isFinish属性而已。

0
zbrong
iT邦新手 5 級 ‧ 2013-04-24 16:38:04

既然只是修改,那就有更简单的做法:首先,控制器中不需要写removeItem方法;其次,将上面的thml代码的第17行换成<input type="checkbox" ng-checked="item.isFinish" ng-model="item.isFinish" />即可。

我要留言

立即登入留言