Multiple View in Single Page

นอกจาก UI Router จะสามารถเรียกใช้งานแบบ view ซ้อน view ได้แล้วยังสามารถ เรียกใช้ view หลายๆหน้าพร้อมกันได้

รู้จักกับ views property

views เป็น property ของ state มีไว้สำหรับกำหนด state ที่มีหลายๆหน้า

โดยลักษณะการกำหนดจะมี property เหมือนกับ state เช่น template, templateUrl, resolve, controller, data เป็นต้น

$stateProvider
	.state('stateName', {
		views: {
			'view1': {
				template: 'someHtml',
				controller: function ($scope) {	... }
			},
			'view2': {
				templateUrl: 'someFile.html'
			},
			'view3': {
				template: 'someHtml',
				resolve: {
					simpleObj: function () {...}
					promiseObj: functon ($http) {...}
				},
				controller: function ($scope, promiseObj, simpleObj) { ... }
			}
		}
	});

โดยในไฟล์ html จะใช้การระบุตำแหน่งของ view ที่จะแสดงผลได้จากใน ui-view directive

<div>
	<!-- Multiple Views -->
	<div ui-view="view1"></div>
	<div ui-view="view2"></div>
	<div ui-view="view3"></div>
	<div ui-view></div> 
</div>

Abstract State

Abstract State เป็น State ที่จะไม่มีการถูกเรียกโดยตรง

แต่จะไว้สำหรับในการทำโครงสร้าง template ต่างๆที่มีการใช้งาน multiple views

และสามารถส่งต่อค่าไปยัง child state ได้ทั้งค่าใน resolve, data และค่า route ที่อยู่ภายใต้ url เดียวกัน

state ที่สืบทอดมาจาก abstract state สามารถใช้ url เดียวกับ abstract ได้ 1 state

โดยมีลักษณะดังนี้

$stateProvider
  .state('admin', {
    abstract: true,
    url: '/admin',
    template: '<div><h1 ui-view="header"></h1><p ui-view="content"></p></div>'
  })
  .state('admin.index', {
    url: '/index',
	views: {
		'header': {
			template: '{{headerText}}',
			controller: function ($scope) {
				$scope.headerText = "Header's Text";
			}
		},
		'content': {
			template: '{{contentText}}',
			controller: function ($scope) {
				$scope.contentText = "Content's Text";
			}
		}
	}
  })

url ของ index คือ /admin/index

ทำต่อจากตัวอย่างที่แล้ว เราจะทำการแบ่งหน้าเว็บของ home ออกเป็น 2 ส่วนโดยมีรายละเอียดดังนี้

angular.module('application', ['ui.router'])
	.config(function ($stateProvider, $urlRouterProvider) {
		$stateProvider
			.state('template', {
				url: '/home',
				abstract: true,
				template: '<div style="background-color:green"><h2 ui-view="firstView"></h2></div>' +
				'<div style="background-color:red"><p ui-view="secondView"></p></div>'
			})
            .state('template.home', {
				views: {
					firstView: {
						template: '<u>{{text}}</u>',
						controller: function ($scope) {
							$scope.text = "firstView";
						}
					},
					secondView: {
						template: '<strong>{{text}}</strong>',
						controller: function ($scope) {
							$scope.text = "secondView";
						}
					}
				}
			})
			.state('contact', { ... })
			.state('about', { ... });
	});

โดยส่วนของ html ก็ยังเป็นตามเดิม

    <div class="container">
		<ul class="nav nav-pills">
			<li><a ui-sref="template.home">Home</a></li>
			<li><a ui-sref="about">about</a></li>
			<li><a ui-sref="contact">contact</a></li>
		</ul>
		<div>
			<p>Next of this line is ui-view</p>
			<div ui-view></div>
		</div>
	</div>

สามารถดูตัวอย่างผลลัพธ์ได้ที่นี่ Demo

ทดสอบเพิ่ม state home2 โดยเป็นลูกของ state template

angular.module('application', ['ui.router'])
	.config(function ($stateProvider, $urlRouterProvider) {
		$stateProvider
			.state('template', {
				url: '/home',
				abstract: true,
				template: '<div style="background-color:green"><h2 ui-view="firstView"></h2></div>' +
				'<div style="background-color:red"><p ui-view="secondView"></p></div>'
			})
            .state('template.home', {
				views: {
					firstView: {
						template: '<u>{{text}}</u>',
						controller: function ($scope) {
							$scope.text = "firstView in Home1";
						}
					},
					secondView: {
						template: '<strong>{{text}}</strong>',
						controller: function ($scope) {
							$scope.text = "secondView in Home1";
						}
					}
				}
			})
			.state('template.home2', {
				url: '/home2',
				views: {
					firstView: {
						template: '<u>{{text}}</u>',
						controller: function ($scope) {
							$scope.text = "firstView in Home2";
						}
					},
					secondView: {
						template: '<strong>{{text}}</strong>',
						controller: function ($scope) {
							$scope.text = "secondView in Home2";
						}
					}
				}
			})
			.state('contact', { ... })
			.state('about', { ... });
	});

ในส่วนของ html ทำการเพิ่ม ลิงค์ไปยัง home2

    <div class="container">
		<ul class="nav nav-pills">
			<li><a ui-sref="template.home">Home</a></li>
			<li><a ui-sref="template.home2">Home</a></li>
			<li><a ui-sref="about">about</a></li>
			<li><a ui-sref="contact">contact</a></li>
		</ul>
		<div>
			<p>Next of this line is ui-view</p>
			<div ui-view></div>
		</div>
	</div>

สามารถดูตัวอย่างผลลัพธ์ได้ที่นี่ Demo

สังเกตได้ว่าทั้ง home และ home2 มีโครงสร้าง template ของ state แบบเดียวกัน