相關內建工具
MessageToast
在使用 MessageToast 之前,必須先在 Controller 的最上方(AMD 載入模組區)將 sap/m/MessageToast 引入。
註解:
- 直接呼叫 show 方法
- 進階參數設定(客製化提示行為):MessageToast.show 除了可以傳入純文字(String)外,還可以傳入一個設定物件(Options Object),讓您可以微調它的行為。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast" // 1. 先在此引入模組
], function (Controller, MessageToast) { // 2. 傳入對應的變數
"use strict";
return Controller.extend("insurance.policymanagement.controller.Main", {
onSavePress: function () {
// 1. 直接呼叫 show 方法
MessageToast.show("保單資料已成功儲存!");
// 2. 進階參數設定(客製化提示行為)
MessageToast.show("處理中,請稍候...", {
duration: 5000, // 提示框顯示的時間(毫秒),預設是 3000 (3秒)
width: "25em", // 提示框的寬度,預設是 15em
my: "center center", // 決定提示框的哪裡(這裏是中心)...
at: "center center", // ...要對齊到螢幕的哪裡(這裏是螢幕正中央)
autoClose: true, // 預設為 true,時間到自動消失
onClose: function() { // 當提示框消失時,要觸發的寫法(Callback 函式)
console.log("提示框已消失,可以進行下一步。");
}
});
}
});
});MessageBox在 SAP UI5 中,sap.m.MessageBox 是一個非常核心且強大的強制對話框(Modal Dialog)工具。與前面介紹、會自動消失的 MessageToast 不同,MessageBox 彈出時會產生一層灰色遮罩,強制中斷使用者的操作。使用者必須親自點擊對話框上的按鈕(如「確認」、「取消」或「關閉」),畫面才會解鎖。它專門用於顯示重要錯誤、警告通知,或是需要使用者確認的關鍵情境(如刪除資料)。以下為您詳細拆解它的基本語法、五大快捷類型、實戰確認確認框(Confirm)以及進階技巧: - 快捷類型與基本用法
使用前,同樣必須先在 Controller 最上方引入 sap/m/MessageBox。框架提供了 5 種最常見的快捷方法,會自動帶入對應的圖示(Icon)與語氣:
① 成功(Success)② 錯誤(Error)1
MessageBox.success("保單合約已正式核准生效。");
用於系統出錯、API 失敗、或不可忽略的檢核失敗。③ 警告(Warning)1
MessageBox.error("網路連線逾時,保單資料儲存失敗,請重新再試。");
④ 資訊(Information)1
MessageBox.warning("您輸入的保額已接近上限,請確認是否正確。");
⑤ 經典對話框(Show)1
MessageBox.information("系統將於今晚 22:00 進行例行性維護。");
實戰最常用:做一個「確認刪除」的對話框(Confirm)1
最原始、客製化彈性最高的方法(後面會詳細說明)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16MessageBox.confirm("您確定要刪除這筆保單資料嗎?(刪除後將無法復原)", {
title: "系統確認", // 對話框標題
actions: [MessageBox.Action.YES, MessageBox.Action.NO], // 顯示的按鈕
emphasizedAction: MessageBox.Action.YES, // 強調(高亮)藍色按鈕
onClose: function (sAction) { // 使用者點選按鈕後的動作
// sAction 會拿到使用者點擊的字串,例如 "YES" 或 "NO"
if (sAction === MessageBox.Action.YES) {
// 執行真正的刪除 API
this._deletePolicyData();
} else {
// 使用者按了取消/否
MessageToast.show("已取消刪除操作。");
}
}.bind(this) // 注意:記得綁定 .bind(this),否則在 function 內會拿不到 Controller 的實體
}); - 進階進階功能:細緻客製化(MessageBox.show)如果您需要更複雜的組合,例如改變標題、自訂按鈕文字、甚至加入特定的 CSS 樣式,可以使用最底層的 MessageBox.show:總結
1
2
3
4
5
6
7
8
9MessageBox.show("這是一則包含詳細說明的通知。", {
icon: MessageBox.Icon.INFORMATION, // 自訂圖示 (ERROR, WARNING, SUCCESS等)
title: "自訂標題",
actions: [MessageBox.Action.OK, MessageBox.Action.CANCEL],
id: "myCustomMessageBoxId", // 設定 ID 方便自動化測試 (OPA5)
details: "這裡可以放超長的詳細錯誤訊息(例如後端回傳的 SQL 報錯或 JSON 堆疊),UI5 會自動把它做成可展開/收合的樣式。",
contentWidth: "30rem" // 限制對話框寬度
});- MessageToast 像「輕輕拍肩」,告訴使用者做完了(3 秒後消失,不干擾)。
- MessageBox 像「拉住手臂」,強制使用者看完了才能走(必須點擊按鈕,有遮罩)。
Dialog
- 新增/編輯資料:點擊「新增保單」時,彈出一個填寫欄位的表單視窗。
- 進階搜尋/篩選:點擊「進階查詢」時,彈出一個包含多個條件組合的搜尋面板。
- 清單選擇:點擊欄位旁的放大鏡,彈出一個客戶清單或保費費率表格供使用者勾選。
實戰最標準寫法:
搭配 Fragment 載入在 SAP UI5 的最佳實踐中,我們絕對不會用 JavaScript 程式碼去刻 Dialog 裡面的控制項。我們會把 Dialog 的外殼與內容寫在一個獨立的 XML Fragment 檔案中,並在 Controller 動態載入它。
步驟一:建立 XML Fragment (例如:view/fragment/CreatePolicyDialog.fragment.xml)
1 | <core:FragmentDefinition |
步驟二:在 Controller 中動態載入與開啟 (SAP UI5 新版非同步標準寫法)在 Controller 中,我們必須在使用者點擊按鈕時去載入這個 Fragment,並將它附加(addDependent)到當前的 View 上,這樣彈窗才能共享 View 的 Data Model(資料模型)與 i18n 語系。
1 | sap.ui.define([ |
Fragment 路徑 (配合 resource-roots) 從哪裡看?
要找出 Fragment 的正確引用路徑,您必須結合 index.html(或初始化設定)中的 data-sap-ui-resource-roots 與專案的實體資料夾結構。其核心公式為:[Resource Roots 的 Key] . [資料夾名稱] . [Fragment 檔名] (注意:不加 .fragment.xml 後綴)。
1. 第一步:去 index.html 找出地圖根路徑(Key):
打開您專案的入口網頁(通常是 index.html),尋找 sap-ui-bootstrap 段落。假設您看到以下設定:
1 | <script id="sap-ui-bootstrap" |
這裡得到的線索:my.navigation.app 這個字串,就代表專案的根目錄(./,也就是 webapp 資料夾)。
2. 第二步:對照您的專案資料夾結構(目錄樹)
webapp (根目錄,對應上方的 "./")
1 | ┣ controller |
- 核心技術重點複習(必記)
- 為什麼不直接寫在 View.xml 裡面?
如果把 Dialog 直接寫在 Main.view.xml 裡,網頁一打開時,即使使用者沒點按鈕,瀏覽器也會順便渲染 Dialog 的 DOM,會拖慢首頁載入速度。用 Fragment 拆開,可以達到「用到時才載入(Lazy Loading)」的效能優化。
- oView.addDependent(oDialog) 的作用是什麼?
Dialog 在網頁結構中是跳出在最外層的( 層級),不屬於任何 View。加上這行後,Dialog 就變成了 View 的「小跟班」,能自動繼承主頁面的所有資料模型(Models)。
- this.byId("dialogInput") 的陷阱
在 Fragment.load 時有設定 id: oView.getId(),所以在 Controller 中不論是主畫面還是彈窗內的控制項,都可以統一用 this.byId("元件ID") 輕鬆抓到!
Button
在 SAPUI5 框架中,sap.m.Button 是最基礎且頻繁使用的控制項(Control)之一,主要用於讓使用者透過點擊、輕觸或鍵盤按鍵來觸發特定的商務邏輯或操作。 它符合 SAP Fiori 設計規範,內建了多種視覺樣式與狀態設定。
核心屬性 (Properties)
- 在定義一個 Button 時,你可以透過以下常用屬性來調整它的外觀與行為:
- text:按鈕上顯示的文字字串。
- icon:按鈕內嵌的圖示,通常使用 SAP 圖示庫(例如 sap-icon://save)。
- enabled:控制按鈕是否可供點擊(預設為 true,設為 false 則變成灰色不可用狀態)。
- type:按鈕的語意類型(例如 Default、Accept 綠色成功、Reject 紅色拒絕、Emphasized 藍色強調)。
- width:按鈕的寬度,可使用 CSS 單位(例如 100px 或 auto)。
核心事件 (Events)
press:這是按鈕最關鍵的事件,當使用者點擊、輕觸或在聚焦時按下 Enter/Space 鍵,就會觸發綁定的 JavaScript 函式。
代碼範例
1 | <mvc:View |
控制器 (Controller)
1 | sap.ui.define([ |
Label
在 SAP UI5 中,sap.m.Label 是一種專門用來顯示「文字標籤」的 UI 控制項(Control)。它最常見的用途是放在輸入框(如 sap.m.Input)、下拉選單或核取方塊的前面或上方,用來提示使用者該欄位需要填寫或選擇什麼內容。
- 核心特性與重要屬性
- text 屬性:用來設定標籤要顯示的文字。通常會透過資料綁定 (Data Binding) 連接到 i18n 國際化語系檔案,以支援多國語言。
- labelFor 屬性: 這是 Label 最關鍵的關聯屬性。你需要將它設定為對應輸入控制項的 id(例如:labelFor="myInputId")。這樣做有兩大好處:
- 無障礙螢幕閱讀器支援 (Accessibility):讓盲人或視障使用者使用的螢幕閱讀器能正確讀出該輸入框的含義。
- 點擊導向:使用者用滑鼠點擊該 Label 文字時,游標會自動聚焦(Focus)到對應的輸入框中。
- required 屬性:當設為 true 時,標籤文字的前面或後面會自動出現一個紅色的星號(*),用來視覺化提示使用者該欄位為「必填欄位」。
- 樣式調整::支援透過屬性微調設計,例如設定文字加粗(design="Bold")或文字對齊方式(textAlign)。
程式碼範例 (XML View)在 SAP UI5 的檢視畫面(View)中,通常會結合佈局控制項(如 Form)一起使用:
1 | <mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:f="sap.ui.layout.form"> |
input
sap.m.Input 是 SAP UI5 框架中最核心的文字輸入元件
- 基礎屬性:
- value:控制或綁定輸入欄位的文本內容。
- placeholder:當欄位為空時顯示的提示文字。
- type::定義輸入類型,例如 Text(文字)、Number(數字)、Password(密碼)、Email 或 Tel(電話)。
- 輸入建議 (Suggestions):
- 透過設定 showSuggestion="true",當使用者打字時,元件會自動下拉匹配 JSON 模型或 OData 中的數據清單。
- 值說明 (Value Help / F4 Help):設定 showValueHelp="true" 後,欄位右側會出現一個放大鏡或正方形圖示。當使用者點擊時,會觸發 valueHelpRequest 事件,通常用於彈出一個對話視窗(Select Dialog)供使用者搜尋並選擇複雜的資料(例如:客戶編號、工廠代碼)。
- 值狀態 (Value State): 支援 valueState 屬性(如 Error、Warning、Success、Information、None),常與 valueStateText 搭配,在表單驗證失敗時向使用者顯示紅框與錯誤訊息。
常見事件 (Events)- 開發者通常會監聽以下事件來控制商業邏輯:
- liveChange:當使用者每輸入或刪除一個字元時即時觸發,常用於即時字數檢查或動態過濾。
- change:當欄位失去焦點(Blur)且內容已被改變時觸發,最常用於欄位格式驗證。
- submit:當使用者在欄位內按下 Enter 鍵時觸發,適合用來執行表單提交或搜尋。
- suggestionItemSelected:當使用者從下拉的輸入建議清單中選中某個項目時觸發。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31<mvc:View
controllerName="my.app.controller.Main"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:core="sap.ui.core">
<VBox class="sapUiSmallMargin">
<Label text="產品編號輸入 (請試著打 'A'、按 Enter 或點擊放大鏡)" labelFor="myInput" />
<Input
id="myInput"
placeholder="請輸入產品代碼..."
showSuggestion="true"
showValueHelp="true"
liveChange="onLiveChange"
change="onChange"
submit="onSubmit"
suggestionItemSelected="onSuggestionItemSelected"
valueHelpRequest="onValueHelpRequest">
<!-- 設定輸入建議的下拉選單資料 -->
<suggestionItems>
<core:Item key="A001" text="Apple iPhone" />
<core:Item key="A002" text="Asus Laptop" />
<core:Item key="B001" text="BMW Car" />
</suggestionItems>
</Input>
</VBox>
</mvc:View>MultiInput :多選表單- 主畫面 MultiInput 控制項
- showValueHelp="true": 顯示右側開窗圖示
- valueHelpOnly="true": 唯讀開窗模式。禁止使用者手動鍵盤輸入,限制只能透- 過點擊圖示或整條輸入框來觸發彈窗,確保資料來源的一致性[1]。
- tokenChange: 當輸入框裡面的『標籤(Token)』發生變動時,立刻發出通知。」
1
2
3
4
5
6
7
8
9
10
11
12//xml
<VBox class="sapUiMediumMargin">
<Label text="主約險種" labelFor="mainInsuranceInput" class="sapUiTinyMarginBottom" />
<MultiInput
id="mainInsuranceInput"
width="100%"
showValueHelp="true"
valueHelpOnly="true"
valueHelpRequest="openMainInsuranceDialog"
tokenChange="monitorMainInsuranceSelectDialog"
/>
</VBox>controller js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117// 檔案:controller/DialogInput.controller.js
sap.ui.define([
"my/navigation/app/controller/BaseController",
"sap/ui/core/Fragment",
"sap/ui/model/json/JSONModel",
"sap/m/Token",
"sap/ui/model/Filter",
"sap/ui/model/FilterOperator"
], function (BaseController,Fragment,JSONModel,Token,Filter,FilterOperator) {
"use strict";
return BaseController.extend("my.navigation.app.controller.DialogInput", {
// 初始化
onInit: function () {
// 模擬後端獲取的險種陣列數據
var oData = {
mainInsurances: [
{ planCode: "CAB", planName: "南山人壽護您久久終身防癌健康保險" },
{ planCode: "4ISWL", planName: "南山人壽威利久久利率變動型增額終身壽險" },
{ planCode: "20SLTC", planName: "南山人壽全方位長期照顧終身保險" },
{ planCode: "10STCB", planName: "南山人壽優樂康護短期照顧終身健康保險" },
],
};
this.getView().setModel(new JSONModel(oData));
},
// 打開主要險種跳出框
openMainInsuranceDialog: function (oEvent)
{
var oView = this.getView();
console.log('this 打開主約險種',)
// 防呆:避免重複加載 Fragment
if (!this._oMainInsuranceDialog) {
const payload = {
id: oView.getId(),
// ⚠️ 請改為您的專案實際路徑
name: "my.navigation.app.view.fragment.MainInsuranceDialog",
controller: this
}
Fragment.load(payload).then(function (oDialog) {
this._oMainInsuranceDialog = oDialog;
oView.addDependent(this._oMainInsuranceDialog);
this._oMainInsuranceDialog.open();
}.bind(this));
} else {
this._oMainInsuranceDialog.open();
}
},
// 搜尋過濾主要選種
filterMainInsuranceSelectDialog: function (oEvent)
{
var sValue = oEvent.getParameter("value");
var oList = this.byId("idMainSelectDialog-list");
console.log('oList',oList)
var oBinding = oList.getBinding("items");
if (!oBinding) {
return;
}
if (sValue) {
// 針對 code 欄位的過濾器
var oFilterCode = new sap.ui.model.Filter("planCode", sap.ui.model.FilterOperator.Contains, sValue);
// 針對 name 欄位的過濾器
var oFilterName = new sap.ui.model.Filter("planName", sap.ui.model.FilterOperator.Contains, sValue);
// 關鍵點:將 bAnd 設為 false,代表「OR (或)」的邏輯關係
var oCombinedFilter = new sap.ui.model.Filter({
filters: [oFilterCode, oFilterName],
and: false
});
// 4. 執行過濾
oBinding.filter([oCombinedFilter]);
} else {
oBinding.filter([]);
}
},
// 確定主要選種選擇項目 => 點擊「確定」傳回數據並關閉視窗
confirmMainInsuranceSelect: function (oEvent) {
// 獲取附約險種表單id
var oMultiInput = this.byId("mainInsuranceInput");
var aSelectedContexts = oEvent.getParameter("selectedContexts");
// 先清空原本輸入框裡的舊標籤
oMultiInput.removeAllTokens();
if (aSelectedContexts && aSelectedContexts.length > 0) {
var aFinalSelectedArray = [];
// 遍歷使用者在畫面上勾選的所有項目
aSelectedContexts.forEach(function (oContext) {
var oObject = oContext.getObject();
// 1. 將數據收集到陣列中(以便您未來傳給後端 API)
aFinalSelectedArray.push(oObject);
// 2. 即時建立 Token 標籤並塞回主畫面的 MultiInput 顯示
oMultiInput.addToken(new Token({
key: oObject.planCode, // 標籤的內部數值 (Key)
text: oObject.planName // 標籤顯示的文字 (Text)
}));
});
// 💡 這就是您最終拿到的純資料陣列
console.log("最終選取的數據陣列:", aFinalSelectedArray);
}
// 關閉時自動清除搜尋過濾條件,確保下次打開是完整的
oEvent.getSource().getBinding("items").filter([]);
},
cancelMainInsuranceSelect: function (oEvent)
{
oEvent.getSource().getBinding("items").filter([]);
},
});
});