สิ่งที่ควรรู้
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! ***//
}
})
