ถึงเราจะคุ้นเคยกับการใช้งาน 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 ในตอนหน้า รอติดตาม