피오리 앱의 제목은 기본적으로 manifest.json
파일에 있는 sap.app.title
속성으로 설정해서 사용한다. 보통은 {appTitle}
과 같이 i18n
에 있는 메시지를 사용하도록 정의하고 메시지 파일을 수정하여 사용한다. 대부분의 경우 이러한 방식은 편리하기도 하고 문제가 없다.
그러나, 어떤 앱의 경우 실행될 때 받은 파라미터에 따라 다른 제목을 표시해야 하는 경우가 있다. 파라미터에 따라서 출력되는 화면이 아주 상이해서 제목을 변경하지 않으면 혼란스러운 경우나 제목부터 상세 정보를 출력하고 싶은 경우 등이다.
참고로 아래의 내용은 Change SAP Fiori Title Dynamically 글을 정리하고 직접 적용했던 경험을 약간 추가해서 작성되었다.
앱 제목이란
본격적인 내용에 앞서 앱 제목(App Title)이란 단어를 정의하자면, 이 글에서 얘기하는 앱 제목, 혹은 타이틀은 Fiori Launchpad의 Shell Bar
에 있는 타이틀을 뜻한다. Fiori Design Guide에서 소개하는 Application Name
과 같은 의미이다.
라우팅과 타이틀 설정
앱의 manifest.json
파일에 있는 routes
와 targets
설정 항목에서 각 target
별로 타이틀을 지정해줄 수 있다. 아래의 예에서는 각 target
별로 정적인 타이틀을 직접 지정해주거나 메시지 파일을 이용하는 방법을 보여준다.
{
...,
"routes": [{
"pattern": "products/overview",
"name": "ProductsOverview",
"target": "products"
},
...
],
"targets": {
"products": {
"viewPath": "shop.products",
"viewName": "Products",
"title": "Products Overview"
},
"productsDetail": {
"viewPath": "shop.products",
"viewName": "ProductDetails",
"title": "Product {ID}"
},
}
...
}
JSON그러나… 위와 같이 해도 변경은 안된다. 이렇게 설정하면 앱 내부적으로 타이틀 변경에 대한 이벤트(attachTitleChanged)가 발생하고 때 파라미터로 title
값을 포함시키기만 하고 실제로 Fiori 런치패드의 앱 이름을 변경 시키진 못한다.
생각해보면 그럴 만도 하다. SAPUI5 App은 런치패드 위에서 작동하는데 App 레벨에서 설정된 내용이 런치패드의 제목까지 영향을 미치는 것은 자동으로 되기가 좀 어렵지 않겠나?
타이틀 변경 이벤트
위와 같이 manifest.json
으로 targets
별로 타이틀을 정의하면 라우팅이 일어날 때 attachTitleChanged
이벤트가 발생한다. 이 이벤트가 발생하면 파라미터로 받은 설정파일의 타이틀을 이용한다.
아래의 예를 일단 설정된 타이틀을 이벤트 파라미터에서 받는 모습을 보여준다.
this.getRouter().attachTitleChanged( oEvent => {
let sTitle = oEvent.getParameter("title");
document.title = sTitle;
});
JavaScript해당 코드는 컴포넌트 컨트롤러(Component.js)에서 Router
에 이벤트 함수를 등록하고 있고, 이제 이벤트가 발생하면 파라미터로 받은 title
값을 document
에 설정하고 있다.
그러나… 여기까지만 해서도 동작을 안한다. 여기서 사용하는 document
는 HTML 요소를 뜻하지 Fiori 런치패드나 앱과는 무관하다.
ShellUIService 적용
다행히도 앱이 Fiori Launchpad와 서로 상호작용할 수 있는 서비스가 있다. ShellUIService
라고 하는 서비스를 활성화 시켜서 해당 서비스에서 제공하는 setTitle
메소드를 이용하면 실제 피오리 런치패드의 타이틀을 변경할 수 있다. 위의 소스를 아래와 같이 변경한다.
this.getRouter().attachTitleChanged( async(oEvent) => {
let sTitle = oEvent.getParameter("title");
let oService = await this.getService("ShellUIService");
oService.setTitle(sTitle);
});
JavaScript서비스를 가져오고 타이틀을 세팅하는 간단한 구조이다. 위와 같이 this.getService
를 이용해서 ShellUIService
를 호출하기 위해서는 아래와 같이 manifest.json
파일에서 해당 서비스를 주입(Injection) 해줘야 한다.
{
...
"sap.ui5": {
"services" : {
"ShellUIService": {
"factoryName": "sap.ushell.ui5service.ShellUIService"
}
}
}
...
}
JSON위와 같은 구성으로 이제 실제 동작하게 되었다. 다시 정리하면 아래 정도이다.
manifest.json
에 각target
별로 타이틀을 설정해준다.Component.js
에서Router
의attachTitleChanged
이벤트용 함수를 생성한다.- 이벤트 함수에서 파라미터로 전달받은 타이틀을
ShellUIService
의setTitle
함수를 이용해서 적용한다. ShellUIService
를 이용하기 위해서manifest.json
에서 해당 서비스를 주입한다.
App Parameter로 타이틀 변경하기
실제 업무에서 위의 내용을 적용하는 경우도 있겠지만 target
이 분리되지 않고 하나의 동일한 라우팅 경로의 앱 화면이 상황에 따라 다른 제목을 가져야 하는 경우가 있다.
실제 적용했던 사례는 하나의 앱을 여러 개의 타일로 등록하고 각 타일에서 서로 다른 파라미터를 전달하도록 피오리 런치패드를 설정했던 경우이다. 이런 경우 타이틀을 결정하는 요인은 앱 실행 시 전달된 파라미터이다. 이를 이용해서 메시지 ID를 구성하고 메시지 파일에서 읽어오는 방법이 제일 낫다.
// 런치패드로부터 전달된 시작 파라미터에서 아이디를 가져와 모델에 저장.
var oStartupParameters = this.getComponentData().startupParameters;
var sParamId = oStartupParameters.paramId && oStartupParameters.paramId[0];
// 메시지 가져오기
var oResourceBundle = this.getModel("i18n").getResourceBundle();
var sMessage = oResourceBundle.getText(sParamId + ".title");
// 앱 타이틀 변경하기.
this.getRouter().attachTitleChanged( async oEvent => {
let oService = await this.getService("ShellUIService");
oService.setTitle(sMessage);
});
JavaScript크게 어려운 부분은 없다. 기존 샘플코드에서 시작 파라미터를 받아오는 부분이 추가되었고, 이를 이용해서 메시지를 가져오는 부분이 추가되었다. 위의 코드를 Component.js
에 구현해서 실제 작동 시점에 동작하도록 하였다.
당연한 얘기지만, 위의 코드에서 파라미터와 .title
문자열을 합쳐서 메시지를 찾기 때문에 해당 메시지 키의 메시지가 i18n
에 등록되어 있어야 한다.