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'

จากตัวอย่างก่อนหน้านี้เราจะทำการเปลี่ยนการแสดงผลโดยจะแสดงเฉพาะชื่อคน

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! ***//  
   }
})