สิ่งที่ควรรู้
onEnter & onExit property
onEnter เป็น property ของ state จะถูกเรียกใช้เมื่อก่อนที่จะเริ่มต้น state นั้นๆ สามารถนำไปใช้กับการตรวจสอบ permission ได้
onExit เป็น property ของ state จะถูกเรียกใช้เมื่อก่อนที่จะออกจาก state นั้นๆ โดยส่วนมากมักจะใช้ในการยืนยันข้อมูลพวก modal dialog ต่างๆ
$stateProvider.state("stateName", { template: 'someHtml', resolve: { 'someData': 'someValue' }, controller: function($scope, someData){ ... }, onEnter: function(someData){ if(someData){ /*** do something ***/ } }, onExit: function(someData){ if(someData){ /*** do something ***/ } } })
การทำงานของ ฟังก์ชั่นใน state จะเรียงลำดับตามนี้
State Change Events
Event ที่เกี่ยวข้องกับการเปลี่ยนแปลง state มีทั้งหมด 4 Event
- $stateChangeStart
- $stateNotFound
- $stateChangeSuccess
- $stateChangeError
โดย Event ทั้งหมดนั้นจะอยู่ภายใต้ scope ของ $rootScope
$stateChangeStart
Event นี้จะถูกใช้ เมื่อเริ่มการเปลี่ยนจาก state ปัจจุบันไปยัง state ถัดไป
โดยจะมีโครงสร้างฟังก์ชั่นดังนี้
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ ... });
$stateNotFound
Event นี้จะถูกใช้ เมื่อเรียกใช้งาน state ที่ไม่มีอยู่
โดยจะมีโครงสร้างฟังก์ชั่นดังนี้
$rootScope.$on('$stateNotFound', function(event, unfoundState, fromState, fromParams){ console.log(unfoundState.to); // unfound State console.log(unfoundState.toParams); // state parameter console.log(unfoundState.options); // options });
$stateChangeSuccess
Event นี้จะถูกใช้ เมื่อการเปลี่ยนจาก state ปัจจุบันไปยัง state ถัดไปเสร็จสิ้น
โดยจะมีโครงสร้างฟังก์ชั่นดังนี้
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ ... });
$stateChangeError
Event นี้จะถูกใช้ เมื่อเกิดข้อผิดพลาดขึ้นระหว่างการเปลี่ยน state โดยส่วนมากจะเป็นข้อผิดพลาดที่ไม่สามารถโหลด resolve promise ได้
โดยจะมีโครงสร้างฟังก์ชั่นดังนี้
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error){ ... });
การเปลี่ยน state จะมี event เรียงลำดับตามนี้
View Load Events
Event ที่เกี่ยวข้องกับการโหลดหน้าเว็บ (view) มีทั้งหมด 2 Event
- $viewContentLoading
- $viewContentLoaded
โดย Event ทั้งหมดนั้นจะอยู่ภายใต้ scope ของ $rootScope
$viewContentLoading
Event นี้จะถูกใช้ เมื่อเริ่มมีการโหลดหน้าเว็บ ก่อนที่จะทำการ render DOM โดยใช้ $broadcast ในการส่ง event
$scope.$on('$viewContentLoading', function(event, viewConfig){ // Access to all the view config properties. // and one special property 'targetView' // viewConfig.targetView });
$viewContentLoaded
Event นี้จะถูกใช้ หลังจากการ render DOM เสร็จสิ้น โดยใช้ $emit ในการส่ง event
$scope.$on('$viewContentLoaded', function(event){ ... });
ตัวอย่างการทำงานของ Event ต่างๆ
ใน config กำหนด state ขึ้นมา 3 state
angular.module('application', ['ui.router']) .config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('one', { url: '/one', template: '<p>this is state one</p><p ui-view></p>' }) .state('one.two', { url: '/two', template: '<p>this is state one-two</p>', }) .state('three', { url: '/three', template: '<p>this is state three</p>', }) });
ใน html ทำการกำหนด link ไปยัง state ต่างๆ
<div class="container"> <ul class="nav nav-pills"> <li><a ui-sref="one">State One</a></li> <li><a ui-sref="one.two">State Two</a></li> <li><a ui-sref="three">State Three</a></li> </ul> <div> <p>Next of this line is ui-view</p> <div ui-view></div> </div> </div>
เพิ่มฟังก์ชั่น onEnter และ onExit ให้กับแต่ละ state
.state('one', { url: '/one', template: '<p>this is state one</p><p ui-view></p>', onEnter: function () { console.log("[onEnter]State One onEnter"); }, onExit: function () { console.log("[onExit]State One onExit"); }, controller: function () { console.log("[controller]State One Controller"); } }) .state('one.two', { url: '/two', template: '<p>this is state one-two</p>', onEnter: function () { console.log("[onEnter] State One.Two onEnter"); }, onExit: function () { console.log("[onExit] State One.Two onExit"); } }) .state('three', { url: '/three', template: '<p>this is state three</p>', onEnter: function () { console.log("[onEnter] State Three onEnter"); }, onExit: function () { console.log("[onExit] State Three onExit"); }, controller: function () { console.log("[controller] State Three Controller"); } });
เพิ่มข้อความแสดงใน log โดยกำหนด Event ใน $rootScope
angular.module('application', ['ui.router']) .config(function ($stateProvider, $urlRouterProvider) { ... }) .run(function ($state, $rootScope) { // State Change Event $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { console.log("[$stateChangeStart] From: ", (fromState.name) ? fromState.name: "No State", "To: ", toState.name); }); $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { console.log("[$stateChangeSuccess] From: ", (fromState.name) ? fromState.name: "No State", "To: ", toState.name); }); // View Loading Event $rootScope.$on('$viewContentLoading', function (event, viewConfig) { console.log("[$viewContentLoading] View Loading..."); }); $rootScope.$on('$viewContentLoaded', function (event) { console.log("[$viewContentLoaded] Loaded Complete"); }); });
สามารถดูตัวอย่างผลลัพธ์ได้ที่นี่ Demo
สังเกตได้ว่า เมื่อมีการเปลี่ยนแปลง state จะมีการทำงานของ stateChange Event และ viewLoad Event
โดยจะทำ stateChange Event ก่อน viewLoad Event