เนื้อหาตอนที่ 4 จะเป็นตอนสุดท้าย ที่ยึดจากตัวอย่างเว็บไซต์
อ่านเนื้อหาก่อนหน้าได้ที่
เพิ่ม ลบ แก้ไข รายการ ด้วย angularjs ตอนที่ 3
https://www.ninenik.com/content.php?arti_id=517 via @ninenik
จะเห็นว่าการอธิบายการศึกษา angurlarjs จากเนื้อหาที่ผ่านๆ มา จะไม่ได้
เน้นไปที่พื้นฐาน หรือการเริ่มต้นจากง่ายไปยาก แต่จะเป็นการ
เรียนรู้ angularjs แบบกว้าง และค่อยเจาะลึกไปทีละส่วน
เนื้อหาในตอนนี้ก็ยังเหมือนเดิม มีบางจุดที่เราไม่รู้โดยละเอียด
ว่ามาได้อย่างไร แต่ขอให้เข้าใจแบบกว้างไป หรือเข้าใจคร่าวๆ เป็นพอ
ให้รู้ว่า การทำงานของ ตัวอย่างนี้เป็นอย่างไร
ตัวอย่างสำหรับตอนที 4 นี้ เราจะมารู้จัก
- การสร้าง components หรือเหมือนสร้าง รูปแบบแท็ก html
ขึ้นมาเฉพาะ แล้วใช้งาน ด้วย angularjs
- การใช้งาน Filter components เข่น currency number และ date
- การใช้งาน directive ngPluralize ใน html จะเขียน ng-pluralize
- การใช้งาน service $locate
เริ่มต้นไฟล์แรก index.html
<!DOCTYPE html> <html ng-app="app"> <head> <meta charset="utf-8" /> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.min.js"></script> <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css" /> <script src="components.js"></script> <script src="app.js"></script> <title>My Learn AngularJs 4</title> </head> <body> <br> <div class="container"> <tabs> <pane title="Localization"> Date: {{ '2012-04-01' | date:'fullDate' }} <br> Currency: {{ 123456 | currency }} <br> Number: {{ 98765.4321 | number }} <br> </pane> <pane title="Pluralzation"> <div ng-controller="BeerCounter"> <div ng-repeat="beerCount in beers"> <ng-pluralize count="beerCount" when="beerForms"></ng-pluralize> </div> </div> </pane> </tabs> </div> </body> </html>
1. บรรทัดที่ 2 กำหนด ng-app สำหรับใช้งาน
<html ng-app="app">
2. บรรทัดที่ 5-8 เรียกใช้ไฟล์ css และ ก็ javascript ตัวนี้ไม่มีอะไร หากยังสงสัย
ให้กลับไปอ่านเนื้อหาก่อนหน้า สำหรับ บรรทัดที่ 7-8 จะเป็น ไฟล์ js ที่เราจะต้องสร้าง
ขึ้นมา
3. บรรทัดที่ 17-30 จะเห็นว่า มีการกำหนดแท็ก tabs และก็ pane ให้เสมือนเป็น html แท็ก
เฉพาะที่ใช้ได้สำหรับ angularjs โดยเมื่อ complie ก็จะได้เป็น html แท็กทั่วไปเช่น div
บรรทัดที่ 18 มีการกำหนด title ให้กับแท็ก pane ตัวแรก ซึ่งจะมีการเอาข้อมูลตรงนี้ไปใช้งาน
บรรทัดที่ 19-21 ส่วนนี้ เป็นการใช้งาน filter component ของ angularjs โดยข้อมูลส่วนนี้
สามารถแสดงผลขึ้นกับ service $locate เช่น ถ้า ถ้าแสดง
{{ '2012-04-01' | date:'fullDate' }} คือ {{ 'ข้อมูล' | date:รูปแบบ }}
ดังนั้นค่าที่ได้ ก็จะเป็น Sunday, April 1, 2012 ตามรูปแบบ fullDate แบบนี้เป็นต้น
$locate ก็จะเป็นการระบุตำแหน่ง ประมาณว่าเราใช้จากที่ไหน รูปแบบภาษาก็จะเปลี่ยน
ไปตามพื้นที่นั้นๆ อย่างประเทศไทย ก็จะใช้รหัสประเทศ $locate.id=th_th
แต่เท่าที่สังเกตุค่าที่กำหนดสำหรับภาษาไทย ไม่ได้มาพร้อมกับไฟล์ angularjs ดังนั้นจึงแสดง
เป็นค่าเริ่มต้น คือ ภาษาอังกฤษ
กรณีใช้ภาษาไทยหรือ ภาษาอื่นๆ สามารถ inlude ไฟล์ js จากลิ้งค์นี้ได้ ในที่นี้ให้เข้าใจคร่าวๆ ไปก่อน
<script src="https://code.angularjs.org/1.0.2/i18n/angular-locale_th-th.js"></script>
บรรทัดที่ 23 มีการกำหนด title ให้กับแท็ก pane ตัวที่สอง ซึ่งจะมีการเอาข้อมูลตรงนี้ไปใช้งาน
บรรทัดที่ 24 กำหนด ngController (สังเกตว่า ถ้าเรียกชือ จะใช้แบบไม่มีเครื่องหมายขีด ค้่น และ
จะมีรูปแบบ camelCase) เท่ากับ BeerCounter สำหรับแสดงการนับจำนวนเบีบร์
บรรทัดที่ 25 อันนี้จะคุ้นเคยกับ ngRepeat ใช้สำหรับวนลูปแสดงข้อมูลซ้ำ ตามจำนวน
บรรทัดที่ 26 มีการใช้งาน ngPluralize เป็นรูปแบบหนึ่งของการแสดงข้อมูล แบบข้อควาาม คล้าย
คำพหุพจน์เรียกจำนวน เช่น ตัวเลข 0 อาจจะใช้คำแทนว่า ไม่มีรายการใดๆ
<ng-pluralize count="beerCount" when="beerForms"></ng-pluralize>
รูปแบบ จะมี count="beerCount" ให้เข้าใจคือ ถ้า จำนวน beerCount = 0
แล้ว when="beerForms" ให้ไปใช้รูปแบบ จากค่าที่กำหนดใน beerForms
ตัวส่วนหนึ่งของไฟล์ app.js ที่เกี่ยวข้องด้านล่าง เกี่ยวกับการกำหนดค่า
$scope.beerForms = { 0: 'no beers', one: '{} beer', other: '{} beers' };
จะเห็นว่า ถ้า จำนวนตัวเลขไม่ตรง อย่างเช่น พอ beerCount เท่า 4
รูปแบบที่จะถูกใช้คือ other: '{} beers' การแสดงผลก็จะเป็นคำว่า 4 beers
โดยเครื่องหมาย {} จะแสดงด้วยตัวเลขจำนวนนั้นๆ
ไฟล์ที่สอง components.js
ไฟล์นี้จะเป็นการกำหนดคำสั่ง ให้ทำการ conplie แท็กที่เรากำหนดเป็น components
หรือคล้าย html แท็กที่เรากำหนดขึ้นเอง เปลี่ยนเป็นแท็กมาตรฐานของ html ในที่นี้คือ
แท็ก tabs และ pane โดยสร้างจาก template คำอธิบาย จะแสดงในโค้ด
angular.module('components', []) // สร้าง module ชื่อ components .directive('tabs', function() { //กำหนดรูปแบบของแท็ก tabs return { // สงค่ากลับเมื่อกำหนดรูปแบบแล้ว restrict: 'E', // กำหนดรูปแบบของแท็กเป็น E หรือคล้าย element เช่น <tabs></tabs> // A attributes ,C css class, M comment transclude: true, // กำหนดให้สามารถแทนที่ ข้อมูลที่กำหนดด้วย ng-transclude ได้ scope: {}, // กำหนด isolate scope ใช้แทน scope หลัก controller: function($scope, $element) { // สรัาง controller ให้ tabs var panes = $scope.panes = []; // เมื่อเริ่มเรียกใช้ กำหนดให้เป็น array ว่าง // console.log("ลำดับทำงานที่ 1"); $scope.select = function(pane) { // กำหนดฟังก์ชั่น select ให้ controller // console.log("ลำดับทำงานที่ 4"); angular.forEach(panes, function(pane) { // วนลูปการ tabs ทั้งหมด pane.selected = false; // กำหนดให้ค่า การถูกเลือก เป็น false ทุกอันก่อน }); pane.selected = true; // แล้วกำหนด tabs ที่เลือก ให้เป็น true } this.addPane = function(pane) {// กำหนดฟังก์ชั่น addPane ให้ controller // console.log("ลำดับทำงานที่ 3 จะมีสองรอบ"); if (panes.length == 0) $scope.select(pane); // ไปทำงานตรงนี้ก่อน เนื่องจากเริ่มต้นกำหนด array ว่าง // console.log("ลำดับทำงานที่ 5 จะมีสองรอบ"); panes.push(pane); // เพิ่มค่า array } }, template: // template สำหรับแสดง tabs '<div class="tabbable">' + '<ul class="nav nav-tabs" role="tablist">' + // รูปแบบ css tabs ของ bootstrap '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+ // วนลูปสร้าง tabs แสดงถ้าถูกเลือก '<a href="" ng-click="select(pane)">{{pane.title}}</a>' + // แสดงหัวข้อ tabs ถ้าคลิก ให้ถูกเลือก '</li>' + '</ul>' + '<div class="tab-content" ng-transclude></div>' + //เนื้อหาจากแท็ก pane ที่ compile แล้ว จะมาแทรกส่วนนี้ '</div>', replace: true // ให้ไปแทนที่แท็ก <tabs> }; }) .directive('pane', function() { //กำหนดรูปแบบของแท็ก pane return { // สงค่ากลับเมื่อกำหนดรูปแบบแล้ว require: '^tabs', // เรียกใช้งาน tabs directive ผ่าน link ฟังก์ชั่นด้านล่าง restrict: 'E', // กำหนดรูปแบบของแท็กเป็น E หรือคล้าย element เช่น <tabs></tabs> // A attributes ,C css class, M comment transclude: true, // กำหนดให้สามารถแทนที่ ข้อมูลที่กำหนดด้วย ng-transclude ได้ scope: { title: '@' }, // กำหนด isolate scope และมีการส่งค่า title ของ pane ไปใช้งานใน template link: function(scope, element, attrs, tabsCtrl) {// ส่งค่าที่จะเป็นไป complie สร้าง html // console.log("ลำดับทำงานที่ 2 จะมีสองรอบ"); // tabsCtrl คือ controller ของ tabs ที่ถูกเรียกใช้งานจาก require // จะมีการส่งค่าไปสองครั้ง คือ ตามจำนวนของ pane tabsCtrl.addPane(scope); // ใช้งาน controller ของ tabs เรียกใช้ฟังก์ชั่น addPane }, template: // template นี้จะถูกแทรกเข้าไปในส่วนของ ng-transclude ของ tabs '<div class="tab-pane" ng-class="{active: selected}" ng-transclude>' + // สำหรับนำข้อมูลในแท็ก pane มาแทรกในนี้อีกที '</div>', replace: true // ให้ไปแทนที่แท็ก <pane> }; })
console.log ในคำอธิบาย จะแสดงถึงลำดับการทำงาน ของไฟล์นี้
เริ่มต้น ลำดับที่ 1 สร้าง complie และสร้าง controller ของ แท็ก tabsก่อน
จากนั้น เริ่ม ทำการ complie แท็ก pane วนสองครั้ง ตามจำนวนแท็ก pane
ในแต่ละครั้งของการ complie แท็ก pane ก็จะไปทำงานในฟังก์ชั่น select และตามด้วย
ฟังก์ชั่น addPane ของ controller tabs ตามลำดับเป็นต้น
ไฟล์ที่สอง components.js ไม่มีคำอธิบาย
angular.module('components', []) .directive('tabs', function() { return { restrict: 'E', transclude: true, scope: {}, controller: function($scope, $element) { var panes = $scope.panes = []; $scope.select = function(pane) { angular.forEach(panes, function(pane) { pane.selected = false; }); pane.selected = true; } this.addPane = function(pane) { if (panes.length == 0) $scope.select(pane); panes.push(pane); } }, template: '<div class="tabbable">' + '<ul class="nav nav-tabs">' + '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+ '<a href="" ng-click="select(pane)">{{pane.title}}</a>' + '</li>' + '</ul>' + '<div class="tab-content" ng-transclude></div>' + '</div>', replace: true }; }) .directive('pane', function() { return { require: '^tabs', restrict: 'E', transclude: true, scope: { title: '@' }, link: function(scope, element, attrs, tabsCtrl) { tabsCtrl.addPane(scope); }, template: '<div class="tab-pane" ng-class="{active: selected}" ng-transclude>' + '</div>', replace: true }; })
ไฟล์ที่สามสุดท้าย app.js
ไฟล์นี้ จะทำในส่วนของ การใช้งาน $locate และการใช้งาน ngPluralize ให้ html แท็กจะใช้
ng-pluralize คำอธิบายจะแสดงในโค้ด
angular.module('app', ['components']) // สร้าง module ชื่อ app และมีการเรียกใช้งาน // module components ที่ถูกสร้าง จากไฟล์ components.js // จัดการเนื้อหาในส่วนของ BeerCounter ซื่งเป็นกำหนดไว้ใน pane ตัวที่สอง .controller('BeerCounter', function($scope, $locale) { // มีการใช้งาน service $locate // กำหนดค่า module data ชื่อ beers เป็น array จำนวน $scope.beers = [0, 1, 2, 3, 4, 5, 6]; if ($locale.id == 'en-us') { // ตรวจสอบ sevice ถ้าเป็นพื้นที่ en-us อเมริกา // ส่วนนี้จะถูกนำไปใช้งานกับ ngPluralize directive $scope.beerForms = { // กำหนดค่ารูปแบบให้กับ module data ชื่อ beerFomrms 0: 'no beers', // ถ้าตัวเลขเป็น 0 ให้แสดง คำว่า no beers แทน one: '{} beer', other: '{} beers' }; } else { // พื้นที่อื่นๆ ที่นี้สมมติเป็นภาษาไทย $scope.beerForms = { // กำหนดค่ารูปแบบให้กับ module data ชื่อ beerFomrms 0: 'ไม่มีซักกระป๋อง', one: '{} กระป๋อง', few: '{} กระป๋อง', other: '{} กระป๋อง' }; } });
ตามจริงแล้ว ngPluralize เราจะไม่ค่อยได้ใช้งานเท่าไหร่
และยังมีรายละเอียดเกี่ยวกับ ngPluralize พอสมควร แต่คงไม่ได้อธิบายลงละเอียด
อ่านเพิ่มเติม ส่วนนี้ได้
ไฟล์ที่สามสุดท้าย app.js ไม่มีคำอธิบาย
angular.module('app', ['components']) .controller('BeerCounter', function($scope, $locale) { $scope.beers = [0, 1, 2, 3, 4, 5, 6]; if ($locale.id == 'en-us') { $scope.beerForms = { 0: 'no beers', one: '{} beer', other: '{} beers' }; } else { $scope.beerForms = { 0: 'ไม่มีซักกระป๋อง', one: '{} กระป๋อง', few: '{} กระป๋อง', other: '{} กระป๋อง' }; } });
ตัวอย่าง
จบเนื้อหาในตอนที่ 4 เท่านี้ ดูๆ อาจจะงง เอาเป็นว่าทำความเข้าใจกันต่อไป
จบเนื้อหาในตอนที่ 4 เท่านี้ ดูๆ อาจจะงง เอาเป็นว่าทำความเข้าใจกันต่อไป
เนื้อหาตอนต่อไป จะเป็นอเไรรอติดตาม