Resume View에는 이전 튜토리얼 처럼 4 개의 탭이 있다. 하지만 사용자가 Resume 페이지로 이동하면 처음에는 첫 번째 탭만 표시된다.
현재 탭에서 특정 탭으로 바로 이동하거나 탭을 북마크로 지정하는 기능은 추후에 만들도록 한다.
이 단계에서는 쿼리를 매개 변수로 하여 tab에 대한 링크를 활성하여 북마크 기능을 구현한다.
Deep Link는 기본적으로 URL에서 App의 더 깊은 구조와 매개 변수를 직접 참조하는 링크이다.
특정 task나 action을 위해 App에 편리한 entry point가 있도록 북마크로 공유한다.
선택한 tab은 URL에 반영되어야 하지만 예를 들어 처음에 이력서 페이지로 이동할 때 tab을 생략 할 수도 있다.
Routing and Navigation - Step 9.
{
...,
"sap.ui5": {
...
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "sap.ui.demo.nav.view",
"controlId": "app",
"controlAggregation": "pages",
"transition": "slide",
"bypassed": {
"target": "notFound"
}
},
"routes": [{
"pattern": "",
"name": "appHome",
"target": "home"
}, {
"pattern": "employees",
"name": "employeeList",
"target": "employees"
}, {
"pattern": "employees/{employeeId}",
"name": "employee",
"target": "employee"
}, {
"pattern": "employees/{employeeId}/resume:?query:",
"name": "employeeResume",
"target": "employeeResume"
}],
"targets": {
...
}
}
}
}
이전까지는 webapp/index.html#/employees/3/resume
으로 직원의 이력서 페이지로 이동을 했다. IconTabBar 컨트롤에 의해 구현 된 첫 번재 Tab을 항상 선택했다.
여기서 선택된 특정 탭을 사용하여 페이지를 직접 열거나 북마크 기능을 추가하려면 URL 패턴에 query
매개 변수를 추가해야 한다.
webapp/index.html#/employees/3/resume?tab=Project
와 같이 url로 허용이 된다. 쿼리 매개 변수는 표시할 tab을 정의한다.
descriptor 파일에서 라우트 패턴을 employees/{employeeId}/resume:?query:
로 변경을 한다. ?:query:
부분은 매개 변수를 사용하여 query로 전달할 수 있고
패턴과 일치하는 이벤트에서 처리 할 수 있다.
note:
?:query:
매개 변수는:
로 시작해서:
로 끝난다. 이는 옵션 사항으로 필수로 설정하기 위해선{?query}
로 사용하면 {}사이의 모든 항목은 필수 항목으로 간주된다.
<mvc:View
controllerName="sap.ui.demo.nav.controller.employee.Resume"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:f="sap.ui.layout.form"
busyIndicatorDelay="0">
<Page
title="{i18n>ResumeOf} {FirstName} {LastName}"
id="employeeResumePage"
showNavButton="true"
navButtonPress="onNavBack"
class="sapUiResponsiveContentPadding">
<content>
<IconTabBar
id="iconTabBar"
class="sapUiResponsiveContentPadding"
binding="{Resume}"
select="onTabSelect"
selectedKey="{view>/selectedTabKey}">
<items>
<IconTabFilter id="infoTab" text="{i18n>Info}" key="Info">
<Text text="{Information}" />
</IconTabFilter>
<IconTabFilter id="projectsTab" text="{i18n>Projects}" key="Projects">
<mvc:XMLView viewName="sap.ui.demo.nav.view.employee.ResumeProjects"></mvc:XMLView>
</IconTabFilter>
<IconTabFilter id="hobbiesTab" text="{i18n>Hobbies}" key="Hobbies">
<Text text="{Hobbies}" />
</IconTabFilter>
<IconTabFilter id="notesTab" text="{i18n>Notes}" key="Notes">
<Text text="{Notes}" />
</IconTabFilter>
</items>
</IconTabBar>
</content>
</Page>
</mvc:View>
URL에서 현재 선택된 탭을 업데이트 하려면 Resume view의 IconTabBar 컨트롤에 select="onTabSelect"
속성을 설정하여 select 이벤트를 등록한다.
selectedKey="{view>/selectedTabKey}"
는 view의 모델에 바인드가 되고 탭에 따라 selectedKey를 넣어 줄 수 있다.
sap.ui.define([
"sap/ui/demo/nav/controller/BaseController",
"sap/ui/model/json/JSONModel"
], function (BaseController, JSONModel) {
"use strict";
var _aValidTabKeys = ["Info", "Projects", "Hobbies", "Notes"];
return BaseController.extend("sap.ui.demo.nav.controller.employee.Resume", {
onInit: function () {
var oRouter = this.getRouter();
this.getView().setModel(new JSONModel(), "view");
oRouter.getRoute("employeeResume").attachMatched(this._onRouteMatched, this);
},
_onRouteMatched : function (oEvent) {
var oArgs, oView, oQuery;
oArgs = oEvent.getParameter("arguments");
oView = this.getView();
oView.bindElement({
path : "/Employees(" + oArgs.employeeId + ")",
events : {
change: this._onBindingChange.bind(this),
dataRequested: function (oEvent) {
oView.setBusy(true);
},
dataReceived: function (oEvent) {
oView.setBusy(false);
}
}
});
oQuery = oArgs["?query"];
if (oQuery && _aValidTabKeys.indexOf(oQuery.tab) > -1){
oView.getModel("view").setProperty("/selectedTabKey", oQuery.tab);
} else {
// the default query param should be visible at all time
this.getRouter().navTo("employeeResume", {
employeeId : oArgs.employeeId,
query: {
tab : _aValidTabKeys[0]
}
},true /*no history*/);
}
},
_onBindingChange : function (oEvent) {
// No data for the binding
if (!this.getView().getBindingContext()) {
this.getRouter().getTargets().display("notFound");
}
},
onTabSelect : function (oEvent){
var oCtx = this.getView().getBindingContext();
this.getRouter().navTo("employeeResume", {
employeeId : oCtx.getProperty("EmployeeID"),
query: {
tab : oEvent.getParameter("selectedKey")
}
}, true /*without history*/);
}
});
});
탭을 클릭하면 onTabSelect 함수가 호출이 된다. 탭의 selectedKey를 감지하고 employeeResume 라우트로 이동하여 URL을 업데이트 한다.
이때 getBindingContext()
를 통해 employeeID
를 넘겨주고 query 매개변수에 object를 전달한다.(event obejct로 부터 selectedKey값을 확인하여 탭으로 넘김)
세번째 인수로 true
전달하면 현재 기록을 바꿔 수동으로 탭을 클릭해도 브라우저 history에는 추가되지 않도록 한다.
JSONModel
을 종송석으로 추가하여 onInit 함수에서 JSONModel을 인스턴스화하여 view model로 사용한다.
var _aValidTabKeys = ["Info", "Projects", "Hobbies", "Notes"];
를 통해 URL의 탭 매개 변수에 대한 유효성 검사를 할 수 있는 키들을 정의한다.
_onRouteMatched
함수는 라우터의 query object
를 참조하는 oQuery 변수를 추가한다. query object가 전달되고 해당 탭의 매개 변수에 유효한 view model값이 있는 경우
/selectedKey
속성을 업데이트 하여 특정 탭을 표시한다.
IconTabBar 컨트롤의 selectedKey 속성은 view>selectedKey에 바인딩 되면 해당 탭이 선택된다. 만약 url에 매치되는 값이 없다면 _aValidTabKeys[0]의 값 Info로 URL이 업데이트 된다.
이제 탭을 클릭하면 URL의 해시가 즉시 변경이 되면서 ui도 업데이트가 되지만 뒤로가기로 브라우저의 히스토리에 저장되지 않음을 알 수 있다.