เนื้อหาในตอนที่ 2 จะยากขึ้นมาหน่อย แต่จะได้ศึกษา ส่วนใช้งาน
เพิ่มขึ้น todo app คือ การทำ ลิสรายการที่ต้องทำ ก็จะอ้างอิง ตัวอย่าง
จากเว็บไซต์ https://angularjs.org/ เช่นดิม
เนื้อหาก่อนหน้า
เรียนรู้ angularjs javascript framework ตอนที่ 1
https://www.ninenik.com/content.php?arti_id=514 via @ninenik
เริ่มต้น ไฟล์ ทดสอบครั้งนี้ มีด้วยกัน 3 ไฟล์ คือ
index.html สำหรับทดสอบ แสดงผล
todo.js สำหรับเขียน javascript
todo.css สำหรับจัดรูปแบบ html
มีอะไรเพิ่มมา ในไฟล์ index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <!DOCTYPE html> < html ng-app = "todoApp" > < head > < meta charset = "utf-8" /> < script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.min.js" ></ script > < script src = "todo.js" ></ script > < link rel = "stylesheet" href = "todo.css" > < title >My Learn AngularJs 2</ title > </ head > < body > < h2 >Todo</ h2 > < div ng-controller = "TodoController" > < span >{{remaining()}} of {{todos.length}} remaining</ span > [ < a href = "" ng-click = "archive()" >archive</ a > ] < ul class = "unstyled" > < li ng-repeat = "todo in todos" > < input type = "checkbox" ng-model = "todo.done" > < span class = "done-{{todo.done}}" >{{todo.text}}</ span > </ li > </ ul > < form ng-submit = "addTodo()" > < input type = "text" ng-model = "todoText" size = "30" placeholder = "add new todo here" > < input class = "btn-primary" type = "submit" value = "add" > </ form > </ div > </ body > </ html > |
1. จะเห็นว่า ในบรรทัดที่ 2 จะมีการกำหนดค่าให้กับ attribute (directive ใน angularjs) ng-app ซึ่งปกติหาก
ไม่มีการกำหนดค่า ให้เข้าใจว่า angularjs จะทำงานกับทั้งหน้าเพจนั้น และการ
กำหนดค่า ให้กับ ng-app ก็เพื่อสำหรับอ้างอิงการเรียกใช้งาน
1 | < html ng-app = "todoApp" > |
ในการทำ todo app จึงมีการตั้งชื่อเป็น todoApp
กำหนดชื่อแบบ camelCase คือ คำตัวเล็กตัวใหญ่สลับกัน คล้ายหลังอูฐ)
2. บรรทัดที่ 6 โหลดไฟล์ javascirpt todo.js ไฟล์นี้เราจะสร้างขึ้นมา และก็ใช้สำหรับ
กำหนดการทำงานของ todo app
3. บรรทัดที่ 7 โหลดไฟล์ css ไฟล์นี้ สร้างขึ้นมา ไม่มีอะไรมาก เป้นแค่การกำหนด style
ให้กับ รายการที่ถูกเลือกแล้ว ให้มี เส้นขึดฆ่า และเป็นข้อความสีเทา
โฟล์ todo.css
1 2 3 4 5 6 7 8 9 | .done-true { /* ชื่อ class สำหรับรายการที่ถูกติ้กเลือก */ text-decoration : line-through ; /* แสดงเส้นขีดฆ่า */ color : grey; /* แสดงเป็นสีเทา */ } ul.unstyled{ /* ชื่อ class สำหรับรายการ แสดงลิสรายการ */ margin : 0 ; padding : 5px ; list-style : none ; } |
4. บรรทัดที่ 13 มี attribute (directive ใน angularjs) ใหม่ คือ ng-controller ให้เข้าใจว่า เป็นการกำหนดชื่อ
class ซึ่งจะมีการเรียกใช้งาน ในที่นี้เขากำหนดเป็นชื่อ TodoController
1 | < div ng-controller = "TodoController" > |
หลักการสำหรับใช้งานคือ การกระทำใดๆ ก็ตามที่เกิดขึ้นภายในส่วนนี้ จะถูกเรียกใช้ผ่าน
class ที่ชื่อ TodoController
5. บรรทัดที่ 14 เป็นการวาง template หรือจัดรูปแบบสำหรับการแสดงผล
โดยอย่าลืมว่า จะใช้ในลักษณะ ปีกกาปิดปิดอย่างละสองอัน {{}}
ด้านในเป็นได้ทั้งชื่อฟังก์ชัน ค่า object หรือชื่อตัวแปร เป็นต้น สำหรับอ้างอิง
1 | < span >{{remaining()}} of {{todos.length}} remaining</ span > |
จากโค้ดบรรทัดนี้ จะเห็นว่า
remaining() คือฟังก์ชั่น
todos.length คือค่าของ objext ชื่อ todos (ในไฟล์ todo.js จะอธิบายที่มาอีกที)
6. บรรทัดที่ 15 มี attribute (directive ใน angularjs) คือ ng-click ให้เข้าใจว่า ตัวนี้คล้าย กับ event onclick
หรือก็คือ เมื่อคลิก ก็จะเรียกใช้ฟังก์ชั่นด้านใน ชื่อ archive() โดยฟังก์ชั่นนี้ ก็คือการ
จัดเก็บรายการที่ถูกติ้กเลือกแล้ว ในตัวอย่างเป็นแค่การลบออกธรรมา
1 | [ < a href = "" ng-click = "archive()" >archive</ a > ] |
7. บรรทัดที่ 16-21 ก็จะเป็น แท็ก html คล้ายกับการวาง template การแสดงข้อมูล
เหตุที่ใช้แท็ก ul ก็เพื่อรองรับ การทำงานในลักษณะวนลูป หรือซ้ำการแสดงข้อมูล
แบบเป็นลิสรายการ
จะเห็นว่า บรรทัดที่ 17 จะมีการกำหนด ng-repeat ให้เข้าใจว่า จะมีการวนลูปแสดง หรือ
การแสดงข้อมูลแท็ก li นี้ซ้ำ ตามจำนวนลิสรายการ เช่นถ้ามีการเพิ่ม รายการเข้าไป ก็จะ
มีการแสดง li แทรกเข้ามา และหากมีการลบ ก็จะทำการลบแท็ก li ออกไป
1 | < li ng-repeat = "todo in todos" > |
สังเกตการกำหนดค่า ng-repeat เป็น "todo in todos"
todo คือค่า instnant หรือ object อ้างอิง ของ property ชื่อ todos อีกที
(todos จะมีอธิบายในไฟล์ todo.js)
บรรทัดที่ 18 บรรทัดนี้ เราจะพบ ng-model ซึ่งได้รู้จักคร่าวๆ มาแล้วในตอนที่ 1
1 | < input type = "checkbox" ng-model = "todo.done" > |
ให้เข้าใจว่า ค่าของ checkbox นี้ มีค่าเท่ากับ ค่าของ todo.done
เช่น todo.done มีค่าเท่ากับ true แล้ว checkbox ก็จะถูกติ้กเลือก
แต่ถ้า todo.don มีค่าเท่ากับ false แล้ว checkbox ก็จะไม่ถุกเลือก เป็นต้น
บรรทัดที่ 19 ส่วนนี้ไม่มีอะไร จะเป็นแค่กำหนด template ของการแสดงข้อความ
ตามค่าที่ได้
1 | < span class = "done-{{todo.done}}" >{{todo.text}}</ span > |
สังเกตแท็ก span นี้ ถ้า todo.done มีค่าเท่ากับ true ก็จะทำให้
class css ของ span ก็จะมีชื่อเป็น done-true ซึ่งก็คือ css ขัดฆ่าในไฟล์ todo.css นั่นเอง
สำหรับ todo.text ก็คือ ข้อความของรายการ ที่แสดงในแท็ก span
8. บรรทัดที่ 22-26 เป็นส่วนของ form สำหรับส่งข้อมูล ในที่นี้ คือการเพิ่ม
ลิ้สรายการ todo มี attibute สำหรับการ submit form คือ ng-submit คล้ายกับ
event submit หรือเหตุการเมื่อมีการกดปุ่มส่ง submit ข้อมูล ตามตัวอย่าง ก็จะไป
เรียกใช้ฟังก์ชั่น addTodo()
1 | < form ng-submit = "addTodo()" > |
บรรทัดที่ 23 input text สำหรับรับค่าลิ้สรายการ โดยใช้ ng-model กำหนดให้ค่าของ
input text นี้อยู่ในชื่อ todoText
บรรทัดที่ 25 ปุ่ม กำหนดให้เป็น type submit เพื่อให้ event submit ทำงาน
9 ส่วนสุดท้าย อันนี้ยากหน่อย มาลองๆ ดูกัน
ไฟล์ toto.js คือส่วนการของการคำสั่ง และการกำหนดให้ทำงานทั้งหมด
คำอธิบายแสดงใน โค้ด
โค้ดไฟล์ todo.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | angular.module( 'todoApp' , []) /* angularjs จะเข้ามาจัดการในส่วนที่กำหนดนี้ <html ng-app="todoApp"> */ .controller( 'TodoController' , [ '$scope' , function ($scope) { /* โดยเข้ามาจัดการเหตุการณ์ ต่างๆ ใน <div ng-controller="TodoController"> ผ่าน $scope object */ /* ส่วนนี้ จะเป็นการกำหนดรายการ todo สองรายการเริ่มต้น โดย todos คือชื่อ property ของ object scope ใน todos property ก็จะมี name และ value */ $scope.todos = [ /* todos นี้มี property type เป็นแบบ array มี name ชื่อ text และ done */ {text: 'learn angular' , done: true }, {text: 'build an angular app' , done: false } ]; /* เมื่อมีการโหลดหน้า app เพจ เริ่มต้น สอง รายการด้านบนนี้ จะถูกนำไปแสดงในแท็ก li ผ่าน ng-repeat ตาม html ด้านล่าง todo จะไปเรียกใช้งาน property todos ของ object scope ผ่านค่า todo in todos iรายการแรก จะถูกติ้กเลือก เพราะ มีค่า todo.done = todos.done = true และรายการ ข้อความใน span จะถูกขีดฆ่า ด้วย css class done-{{todo.done}} = done-{{todos.done}} = done-true {{todo.text}} = todos.text <li ng-repeat="todo in todos"> <input type="checkbox" ng-model="todo.done"> <span class="done-{{todo.done}}">{{todo.text}}</span> </li> */ /* object scope กำหนด method ขอเรียกเป็น ฟังก์ชั่นละกัน ฟังก์ชั่น addTodo() เนื่องจาก property todos เป็น array การเพิ่มข้อมูลเข้าไปจะใช้ คำสั่ง push เพื่อเพิ่ม array <input type="text" ng-model="todoText" size="30" placeholder="add new todo here"> จะเห็นว่า object scope จะดึงค่า input text ด้วยชื่อ todoText โดยเรียกผ่าน $scope.todoText การเพิ่มค่า จะเพิ่มเข้าไป สองค่า คือ text กับ done ค่า text คือค่า จาก input text ส่วนค่า done จะเป็นค่าเริ่มต้น กำหนดให้เป็น false คือยังไม่ถูกติ้กเลือก */ $scope.addTodo = function () { $scope.todos.push({text:$scope.todoText, done: false }); /* เพิ่มค่าเข้าไปใน array todos */ $scope.todoText = '' ; /* หลังจากเพิ่มค่าแล้ว ให้ลบข้อความ ใน input text */ }; /* ส่วนของการแสดงค่า จำนวนรายการ ใน template <span>{{remaining()}} of {{todos.length}} remaining</span> โดย todos.length คือ จะนับค่า รายการใน array todos ทั้งหมด ส่งค่าไปแสดง สำหรับรายการที่ยังไม่ติ้กเลือก หรือรายการคงเหลือ จะใช้ฟังก์ชั่น remaining() */ $scope.remaining = function () { var count = 0; // กำหนดตัวแปร ค่านับเริ่มต้น เป็น 0 angular.forEach($scope.todos, function (todo) { //คำสั่งของ angularjs วนลูปแสดง array todos //ให้ตัวนับจำนวนทั้งหมด บวกค่า ตามเงือนไข count += todo.done ? 0 : 1; // นับเฉพาะรายการ false หรือรายการยังไม่ติ้กเลือก ให้บวกเพิ่ม ทีละ 1 }); return count; // คืนค่า รายการที่ยังไม่ถูกติ้กเลือกทั้งหมด หรือรายการคงเหลือ }; /* ส่วนสุดท้าย กับการใช้งานกับ event click เพื่อกำหนดรายการเป็น archive ที่จริงก็คือรายการลิ้สที่ติ้กเลือกแล้ว และต้องการจัดเก็บ แต่คำสั่ง จะเป็นการลบออก เพื่อดูผลลัพธ์อย่างง่าย [ <a href="" ng-click="archive()">archive</a> ] จะใช้งาน ฟังก์ชั่น archive() โดยในตัวอย่างนี้ เขาจะกำหนด property todos ที่เป็น array ของ object scope ด้วย $scope.todos = []; กำหนดเป็น array ค่าว่าง แล้วเพิ่มค่าไปใหม่ */ $scope.archive = function () { var oldTodos = $scope.todos; // เก็บค่า todos array ทั้งหมดไว้กับตัวแปร array oldTodos แทนก่อน $scope.todos = []; // ล้างค่าตัวเก่า โดย กำหนดเป็น array ค่าว่าง angular.forEach(oldTodos, function (todo) { // นำค่าที่ถูกเก็บในตัวแปร oldTodos วนลูปแสดง // จากนั้น เพิ่มค่าเข้าไปใหม่ ภายในเงื่อนไขว่า เอาเฉพาะ รายการที่ยังไม่ถูกเลือกเท่านั้นไว้ // ซื่อก็คือ รายการที่ todo.done=false ให้เอามาแสดง รายการที่ถูกเลือกแล้ว ไม่เอา if (!todo.done) $scope.todos.push(todo); // รายการที่ todo.done=false ให้เอามาแสดง }); }; }]); |
แบบไม่มีคำอธิบาย โค้ดไฟล์ todo.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | angular.module( 'todoApp' , []) .controller( 'TodoController' , [ '$scope' , function ($scope) { $scope.todos = [ {text: 'learn angular' , done: true }, {text: 'build an angular app' , done: false }]; $scope.addTodo = function () { $scope.todos.push({text:$scope.todoText, done: false }); $scope.todoText = '' ; }; $scope.remaining = function () { var count = 0; angular.forEach($scope.todos, function (todo) { count += todo.done ? 0 : 1; }); return count; }; $scope.archive = function () { var oldTodos = $scope.todos; $scope.todos = []; angular.forEach(oldTodos, function (todo) { if (!todo.done) $scope.todos.push(todo); }); }; }]); |
ตัวอย่าง
ตอนที่ 2 ยาว แต่ถ้าทำความเข้าใจ ก็จะเรียนรู้ได้เร็วขึ้น
ตอนนี้ได้รู้จัก ng-controller ng-click ng-submit ng-repeat
และรู้จัก object scope เพิ่มเข้ามา
ตอนหน้าจะมีอะไรใหม่ รอติดตาม