ถึงเราจะคุ้นเคยกับการใช้งาน scope ในหลายๆ ตัวอย่างที่ผ่านมาแล้ว
แต่อาจจะยังไม่เข้าใจละเอียดมากนัก เนื้อหาตอนนี้ เลยจะมาอธิบายเพิ่มเติม
ตามความเข้าใจของผู้เขียนบทความ
อ้างอิงจาก https://docs.angularjs.org/guide/scope
ใน angularjs จะสามารถเรียกใช้งาน scope ได้อยู่ 2 ส่วน คือ
1. ส่วนที่กำหนดจาก ngApp จะเป็น $rootScope
2. ส่วนกำหนด ใน controller โดยใช้ ngController จะเป็น $scope
โดย angularjs จะใช้วิธีกำหนด css class ชื่อว่า ng-scope
ไว้ในทั้งสองส่วน เช่น
<!DOCTYPE html> <html ng-app> <head> <meta charset="UTF-8"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.min.js"></script> <title>Document</title> </head> <body> <div class="container"> <label>Name:</label> <input type="text" ng-model="yourName" placeholder="Enter a name here"> <hr> <h1>Hello {{yourName}}!</h1> </div> </body> </html>
หมายเหตุ: ใน html หรือ directive ที่กำหนดเอง จะใช้รูปแบบ แบบ spinal-case
เช่น ng-app หรือ ng-controller คล้ายรุปแบบกระดูสันหลัง |-|-|-|-|-|
ส่วนการอ้างอิง จะใช้วิธีเรียกแบบ camelCase หรือหลังอูฐ เช่น ngApp ngController
จากโค้ดด้านบน
ส่วน html แท็กเปิด จะมีการกำหนด css class เข้าไป
<html ng-app="" class="ng-scope">
เนื่องจากตัวอย่างด้านบน ไม่มีการกำหนด ในส่วนของ controller
ดังนั้นค่าตัวแปรต่างที่เรียกใช้ จะเป็นในส่วนของ $rootScope
ส่วนที่มีการกำหนด expression
<h1>Hello {{yourName}}!</h1>
แท็ก h1 จะถุกกำหนด css class ชื่อ ng-binding จะได้เป้น
<h1 class="ng-binding">Hello !</h1>
ngApp ไม่จำเป็นต้องกำหนดในส่วนแท็กเปิด html สามารถกำหนดในส่วนของแท็กเปิด body
<body ng-app>
หรืออื่นๆ ก็ได้ ในหนึ่งไฟล์สามารถมีได้หลายที่ แต่โดยทั่วไปแล้ว
จะกำหนด ที่เดียว และไว้ในส่วนของ แท้กเปิด html
หากมีการกำหนด controller จะต้องมีการเรียกใช้งาน angular.module และกำหนด
ค่าต่างๆ ให้กับ controller ไม่เช่นนั้น ส่วนของ controller ก็จะไม่ทำงาน
โดยจะต้องกำหนดชื่อในกับ ngApp เพื่อใช้ในการสร้าง module ด้วย
เช่น
<!DOCTYPE html> <!--กำหนดชื่อให้กับ ngApp--> <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> <title>Document</title> </head> <body> <!-- เมื่อมีการใช้งาน controller--> <div class="container" ng-controller="myCtrl"> <label>Name:</label> <input type="text" ng-model="yourName" placeholder="Enter a name here"> <hr> <h1>Hello {{yourName}}!</h1> </div> <script type="text/javascript"> angular.module('app',[]) .controller('myCtrl',['$scope',function($scope){ }]); </script> </body> </html>
จากโค้ดตัวอย่างด้านบน จะมีการกำหนด controller ดังนั้น angularjs จะทำการกำหนด
css class ชื่อ ng-scope เข้าไปในส่วนของแท็ก div
<div class="container" ng-controller="myCtrl">
จะได้เป็น
<div class="container ng-scope" ng-controller="myCtrl">
เราสามารถเรียกใช้งาน $rootScope และ $scope โดยการ inject ค่าเข้าไปใน
controller จากโค้ดเป้นการใช้งาน $scope และมีการ inject ค่า $scope เข้าไป
ใน controller
<script type="text/javascript"> angular.module('app',[]) .controller('myCtrl',['$scope',function($scope){ }]); </script>
หากต้องการเรียกใช้งาน $rootScope สามารถทำได้ดังนี้
<script type="text/javascript"> angular.module('app',[]) .controller('myCtrl',['$scope','$rootScope',function($scope,$rootScope){ }]); </script>
$scope จะเป็น child หรือลูกของ $rootScope
ถ้าเปรียบคือ
$rootScope เป็น parent
$scope เป็น child
และเนื่องจาก $rootScope ที่สามารถสืบทอดคุณสมบัติได้ หรือที่เรียกว่า Inheritance
ดังนั่ง property หรือ medthod ที่กำหนด จาก $rootScope ก็จะสามารถเรียกใช้งาน
ใน controller ได้
ดูโค้ดประกอบอธิบาย
<!DOCTYPE html> <!--กำหนดชื่อให้กับ ngApp--> <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> <title>Document</title> </head> <body> <!-- yourName อยู่นอก controller จะไม่สามารถใช้ค่าที่กำหนดจาก scope ใน controller ได้ แต่ สามารถใช้ค่า ที่กำหนดจาก parent ของ $scope หรือ $rootScope --> <p>Hi {{yourName}}</p> <!-- เมื่อมีการใช้งาน controller--> <div class="container" ng-controller="myCtrl"> <label>Name:</label> <input type="text" ng-model="yourName" placeholder="Enter a name here"> <hr> <!-- yourName ที่กำหนด ใน controller สามารถใช้ค่า ที่กำหนดจาก parent ของ scope หรือ $rootScope--> <h1>Hello {{yourName}}!</h1> </div> <script type="text/javascript"> angular.module('app',[]) .controller('myCtrl',['$scope','$rootScope',function($scope,$rootScope){ $rootScope.yourName="demo1"; }]); </script> </body> </html>
จากโค้ดด้านบน จะเห็นว่า ค่า yourName ทั้งในและนอก controller จะมีค่าเท่ากับ demo1
นั้นก็เพราะ $scope สืบทอดค่ามาจาก $rootScope
ทีนี้มาดูกันว่า กลับกัน ค่าที่กำหนดด้วย child หรือ $scope จะไม่สามารถเรียกใช้ นอก controller ได้
ดูโค้ดประกอบ
<!DOCTYPE html> <!--กำหนดชื่อให้กับ ngApp--> <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> <title>Document</title> </head> <body> <!-- yourName อยู่นอก controller จะไม่สามารถใช้ค่าที่กำหนดจาก scope ใน controller ได้ แต่ สามารถใช้ค่า ที่กำหนดจาก parent ของ scope หรือ rootScope --> <p>Hi {{yourName}}</p> <!-- เมื่อมีการใช้งาน controller--> <div class="container" ng-controller="myCtrl"> <label>Name:</label> <input type="text" ng-model="yourName" placeholder="Enter a name here"> <hr> <!-- yourName ที่กำหนด ใน controller สามารถใช้ค่า ที่กำหนดจาก parent ของ scope หรือ $rootScope แต่หากมีการกำหนดค่า ของ $scope ใน controller ค่าที่ได้ จะใช้ค่าของ $scope แทนค่าจาก $rootScope --> <h1>Hello {{yourName}}!</h1> </div> <script type="text/javascript"> angular.module('app',[]) .controller('myCtrl',['$scope','$rootScope',function($scope,$rootScope){ $scope.yourName="demo2"; }]); </script> </body> </html>
ใน controller มีการกำหนดค่า yourName ด้วย $scope ซึ่งเป็น child ของ $rootScope
ดังนั้นจะทำให้ yourName ที่อยู่นอก controller จะเป็น undefined
ส่วน yourName ใน controller จะมีค่าเท่ากับ demo2
สรุปอย่างง่าย:
1. ค่าที่กำหนดจาก $rootScope สามารถใช้งาน ใน controller ใดๆ ก็ได้
2. ถ้าใน controller มีการกำหนด $rootScope และ $scope โดยมีชื่อ หรือ property เดียวกัน เช่น
$rootScope.yourname="demo1"; $scope.yourname="demo2";
แบบนี้ expression ใน controller จะใช้ค่าจาก $scope ซึ่งเท่ากับ demo2
ส่วน expression นอก controller จะใช้ค่าจาก $rootScope ซึ่งเท่ากับ demo1
3. ค่าที่กำหนดจาก $scope จะใช้ได้เฉพาะใน controller นั้นๆ เท่านั้น
ขอต่อรายละเอียดเกี่ยวกับ scope ในตอนหน้า รอติดตาม