สิ่งที่ควรรู้
URL Parameter
โดยปกติจะมีการส่งตัวแปรผ่านมาทาง url และจะทำการเก็บค่าไว้ใน $stateParams
โดยสามารถกำหนดได้ 3 แบบดังนี้
- url: 'url/:id' - ใช้ในกรณีที่มีพารามิเตอร์ปกติ โดยพารามิเตอร์สามารถเป็นอะไรก็ได้
- ยกตัวอย่าง 'url/12345!!', 'url/bob' รวมถึง 'url/'
- ไม่รอบรับกรณี 'url' หรือ 'url/bob/details'
- url: 'url/{id}' - ใช้ในกรณีที่มีพารามิเตอร์ เหมือนกับ :id แต่จะมีรูปแบบของ id ด้วย โดยสามารถระบุได้จาก regex
- ยกตัวอย่าง
// Match only inbox ids that contain // 6 hexidecimal digits url: '/url/{id:[0-9a-fA-F]{6}}', // Or // match every url at the end of `/url` and `/url/id` url: '/url/{id:.*}'
- ยกตัวอย่าง
- url: 'url?query' - ใช้ในกรณีที่มีส่งพารามิเตอร์มาในลักษณะของ query
- ยกตัวอย่าง
// for query parameter url: "/contacts?myParam" // match "/contacts?myParam=value" // for multi parameter url: "/contacts?myParam1&myParam2" // match "/contacts?myParam1=value1&myParam2=value2"
- ยกตัวอย่าง
ในกรณีที่มีพารามิเตอร์จะใช้ ui-sref ใน <a > ดังนี้
<a ui-sref="stateName({id : value})"></a>
Nested Routing
ส่วนที่ UI Router ต่างกับ ngRoute คือ Nested Routing หรือการ Route แบบมีลำดับชั้น ซึ่งใน ngRoute ของ AngularJS ไม่มี
และยังสามารถใช้ view ซ้อนใน view ได้ โดยเรียกใช้ผ่าน ui-view
โดยการใช้งาน Nested Routing จะทำการกำหนดชั้นถัดไปโดยคั่นด้วย . (dot notation)
$stateProvider .state('root', { url: '/root', ... }) .state('root.branch', { url: '/:branchId', ... }) .state('root.branch.element', { url: '/element/{elementId}', ... })
ตัวอย่าง url
root state จะมี URL คือ '/root'
branch state จะมี URL คือ '/root/1'
element state จะมี URL คือ '/root/1/element/2'
ตัวอย่างการใช้งาน Nested Routing
จากตัวอย่างก่อนหน้านี้เราจะทำการเปลี่ยนการแสดงผลโดยจะแสดงเฉพาะชื่อคน
angular.module('application', ['ui.router']) .config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('home', { url: '/home', template: '<p>this is part of home</p>', data: { message: "Welcome Home" }, controller: function ($state) { alert($state.current.data.message); } }) .state('contact', { url: '/contact', template: '<h3>This is Contact</h3>' + '<ul>' + '<li ng-repeat="contact in contacts">' + '<a ui-sref="contact.detail({ id : contact.name})">{{contact.name}}</a>' + '</li></ul>' + '<div ui-view></div>', resolve: { contacts: function ($http) { return $http({method: 'GET', url: 'contacts.json'}) .then(function (response) { return response.data; }); } }, controller: function ($scope, contacts) { $scope.contacts = contacts; } }) .state('about', { url: '/about', template: '<p>Creator is {{name}}</p>', controller: function ($scope) { $scope.name = "Google!!"; } }); });
กำหนด state contact.detail ขึ้นมาโดยแสดงข้อมูลรายละเอียดของคนๆนั้น
angular.module('application', ['ui.router']) .config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('home', { ... }) .state('contact', { ... }) .state('contact.detail', { url: '/detail/:id', template: '<p>{{contact.name}} (age: {{contact.age}}) e-mail: {{contact.email}}</p>', resolve: { contact: function ($http, $stateParams) { return $http({method: 'GET', url: 'contacts.json'}) .then(function (response) { for (i = 0; i < response.data.length; i++) { if (response.data[i] === $stateParams.id) { return response.data[i]; } } }) } }, controller: function ($scope, contact) { $scope.contact = contact; } }) .state('about', { ... }); });
สามารถดูตัวอย่างผลลัพธ์ได้ที่นี่ Demo
ข้อควรรู้เพิ่มเติม
Absolute Route (^)
Absolute Route เป็นการกำหนดให้ url ที่กำหนดเริ่มต้นที่ url นั้นเลย
ตัวอย่างการ route แบบปกติ
$stateProvider .state('contacts', { url: '/contacts', ... }) .state('contacts.list', { url: '/list', ... });
เมื่อ state เป็น [contacts] url ที่แสดงจะเป็น '/contacts'
เมื่อ state เป็น [contacts.list] url ที่แสดงจะเป็น '/contacts/list'
หากใช้ absolute route
$stateProvider .state('contacts', { url: '/contacts', ... }) .state('contacts.list', { url: '^/list', ... });
เมื่อ state เป็น [contacts] url ที่แสดงจะเป็น '/contacts'
เมื่อ state เป็น [contacts.list] url ที่แสดงจะเป็น '/list'
การใช้ตัวแปรใน $stateParams ที่เป็นของ parent state
ในกรณีที่มีการเรียกใช้ $stateParams จะไม่สามารถเรียกใช้ ของ parent ได้โดยตรง
$stateProvider.state('contacts.detail', { url: '/contacts/:contactId', controller: function($stateParams){ $stateParams.contactId //*** Can Use! ***// } }).state('contacts.detail.subitem', { url: '/item/:itemId', controller: function($stateParams){ $stateParams.contactId //*** Can't Use Don't Have Value!! ***// $stateParams.itemId //*** Can Use! ***// } })
โดยเราสามารถใช้งาน $stateParams ของ parent ได้โดยใช้ resolve ช่วยดังนี้
$stateProvider.state('contacts.detail', { url: '/contacts/:contactId', controller: function($stateParams){ $stateParams.contactId //*** Can Use! ***// }, resolve:{ contactId: ['$stateParams', function($stateParams){ return $stateParams.contactId; }] } }).state('contacts.detail.subitem', { url: '/item/:itemId', controller: function($stateParams, contactId){ contactId //*** Can Use!! From Resolve ***// $stateParams.itemId //*** Can Use! ***// } })