เนื้อหาในตอนที่ 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
<!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 ก็เพื่อสำหรับอ้างอิงการเรียกใช้งาน
<html ng-app="todoApp">
ในการทำ todo app จึงมีการตั้งชื่อเป็น todoApp
กำหนดชื่อแบบ camelCase คือ คำตัวเล็กตัวใหญ่สลับกัน คล้ายหลังอูฐ)
2. บรรทัดที่ 6 โหลดไฟล์ javascirpt todo.js ไฟล์นี้เราจะสร้างขึ้นมา และก็ใช้สำหรับ
กำหนดการทำงานของ todo app
3. บรรทัดที่ 7 โหลดไฟล์ css ไฟล์นี้ สร้างขึ้นมา ไม่มีอะไรมาก เป้นแค่การกำหนด style
ให้กับ รายการที่ถูกเลือกแล้ว ให้มี เส้นขึดฆ่า และเป็นข้อความสีเทา
โฟล์ todo.css
.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
<div ng-controller="TodoController">
หลักการสำหรับใช้งานคือ การกระทำใดๆ ก็ตามที่เกิดขึ้นภายในส่วนนี้ จะถูกเรียกใช้ผ่าน
class ที่ชื่อ TodoController
5. บรรทัดที่ 14 เป็นการวาง template หรือจัดรูปแบบสำหรับการแสดงผล
โดยอย่าลืมว่า จะใช้ในลักษณะ ปีกกาปิดปิดอย่างละสองอัน {{}}
ด้านในเป็นได้ทั้งชื่อฟังก์ชัน ค่า object หรือชื่อตัวแปร เป็นต้น สำหรับอ้างอิง
<span>{{remaining()}} of {{todos.length}} remaining</span>
จากโค้ดบรรทัดนี้ จะเห็นว่า
remaining() คือฟังก์ชั่น
todos.length คือค่าของ objext ชื่อ todos (ในไฟล์ todo.js จะอธิบายที่มาอีกที)
6. บรรทัดที่ 15 มี attribute (directive ใน angularjs) คือ ng-click ให้เข้าใจว่า ตัวนี้คล้าย กับ event onclick
หรือก็คือ เมื่อคลิก ก็จะเรียกใช้ฟังก์ชั่นด้านใน ชื่อ archive() โดยฟังก์ชั่นนี้ ก็คือการ
จัดเก็บรายการที่ถูกติ้กเลือกแล้ว ในตัวอย่างเป็นแค่การลบออกธรรมา
[ <a href="" ng-click="archive()">archive</a> ]
7. บรรทัดที่ 16-21 ก็จะเป็น แท็ก html คล้ายกับการวาง template การแสดงข้อมูล
เหตุที่ใช้แท็ก ul ก็เพื่อรองรับ การทำงานในลักษณะวนลูป หรือซ้ำการแสดงข้อมูล
แบบเป็นลิสรายการ
จะเห็นว่า บรรทัดที่ 17 จะมีการกำหนด ng-repeat ให้เข้าใจว่า จะมีการวนลูปแสดง หรือ
การแสดงข้อมูลแท็ก li นี้ซ้ำ ตามจำนวนลิสรายการ เช่นถ้ามีการเพิ่ม รายการเข้าไป ก็จะ
มีการแสดง li แทรกเข้ามา และหากมีการลบ ก็จะทำการลบแท็ก li ออกไป
<li ng-repeat="todo in todos">
สังเกตการกำหนดค่า ng-repeat เป็น "todo in todos"
todo คือค่า instnant หรือ object อ้างอิง ของ property ชื่อ todos อีกที
(todos จะมีอธิบายในไฟล์ todo.js)
บรรทัดที่ 18 บรรทัดนี้ เราจะพบ ng-model ซึ่งได้รู้จักคร่าวๆ มาแล้วในตอนที่ 1
<input type="checkbox" ng-model="todo.done">
ให้เข้าใจว่า ค่าของ checkbox นี้ มีค่าเท่ากับ ค่าของ todo.done
เช่น todo.done มีค่าเท่ากับ true แล้ว checkbox ก็จะถูกติ้กเลือก
แต่ถ้า todo.don มีค่าเท่ากับ false แล้ว checkbox ก็จะไม่ถุกเลือก เป็นต้น
บรรทัดที่ 19 ส่วนนี้ไม่มีอะไร จะเป็นแค่กำหนด template ของการแสดงข้อความ
ตามค่าที่ได้
<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()
<form ng-submit="addTodo()">
บรรทัดที่ 23 input text สำหรับรับค่าลิ้สรายการ โดยใช้ ng-model กำหนดให้ค่าของ
input text นี้อยู่ในชื่อ todoText
บรรทัดที่ 25 ปุ่ม กำหนดให้เป็น type submit เพื่อให้ event submit ทำงาน
9 ส่วนสุดท้าย อันนี้ยากหน่อย มาลองๆ ดูกัน
ไฟล์ toto.js คือส่วนการของการคำสั่ง และการกำหนดให้ทำงานทั้งหมด
คำอธิบายแสดงใน โค้ด
โค้ดไฟล์ todo.js
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
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 เพิ่มเข้ามา
ตอนหน้าจะมีอะไรใหม่ รอติดตาม