SAP UI5 元件工具

相關內建工具

MessageToast
在使用 MessageToast 之前,必須先在 Controller 的最上方(AMD 載入模組區)將 sap/m/MessageToast 引入。

註解:

  1. 直接呼叫 show 方法
  2. 進階參數設定(客製化提示行為):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
    29
    sap.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)以及進階技巧:
  3. 快捷類型與基本用法
    使用前,同樣必須先在 Controller 最上方引入 sap/m/MessageBox。框架提供了 5 種最常見的快捷方法,會自動帶入對應的圖示(Icon)與語氣:
    ① 成功(Success)
    1
    MessageBox.success("保單合約已正式核准生效。");
    ② 錯誤(Error)
    用於系統出錯、API 失敗、或不可忽略的檢核失敗。
    1
    MessageBox.error("網路連線逾時,保單資料儲存失敗,請重新再試。");
    ③ 警告(Warning)
    1
    MessageBox.warning("您輸入的保額已接近上限,請確認是否正確。");
    ④ 資訊(Information)
    1
    MessageBox.information("系統將於今晚 22:00 進行例行性維護。");
    ⑤ 經典對話框(Show)
    1
    最原始、客製化彈性最高的方法(後面會詳細說明)。
    實戰最常用:做一個「確認刪除」的對話框(Confirm)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    MessageBox.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 的實體
    });

  4. 進階進階功能:細緻客製化(MessageBox.show)如果您需要更複雜的組合,例如改變標題、自訂按鈕文字、甚至加入特定的 CSS 樣式,可以使用最底層的 MessageBox.show:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    MessageBox.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
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
<core:FragmentDefinition
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:f="sap.ui.layout.form">

<Dialog id="createPolicyDialog" title="新增保戶資料">
<!-- 內容區:您可以自由塞任何控制項 -->
<content>
<f:SimpleForm editable="true" layout="ResponsiveGridLayout">
<f:content>
<Label text="保戶姓名" required="true" />
<Input id="inputCustomerName" placeholder="請輸入姓名" />

<Label text="身分證字號" />
<Input id="inputCustomerId" placeholder="請輸入身分證" />
</f:content>
</f:SimpleForm>
</content>

<!-- 底部按鈕區 -->
<buttons>
<Button text="儲存" type="Emphasized" press="onSaveDialog" />
<Button text="取消" press="onCloseDialog" />
</buttons>
</Dialog>

</core:FragmentDefinition>

步驟二:在 Controller 中動態載入與開啟 (SAP UI5 新版非同步標準寫法)在 Controller 中,我們必須在使用者點擊按鈕時去載入這個 Fragment,並將它附加(addDependent)到當前的 View 上,這樣彈窗才能共享 View 的 Data Model(資料模型)與 i18n 語系。

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
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/Fragment"
], function (Controller, Fragment) {
"use strict";

return Controller.extend("insurance.policymanagement.controller.Main", {

// 使用者點擊畫面的「新增」按鈕
onOpenDialogPress: function () {
var oView = this.getView();

// 檢查是否已經建立過這個 Dialog 實體,避免重複載入
if (!this._pDialog) {
// 使用 Fragment.load 非同步載入 XML
const query = {
id: oView.getId(), // 確保 Fragment 內的元件 ID 會加上 View 的 ID 作為前綴
name: "my.navigation.app.view.fragment.CreatePolicyDialog", // 這裡填寫剛才建立的 Fragment 路徑 (配合 resource-roots)
controller: this // 關鍵:將此 Controller 綁定給 Fragment,這樣彈窗內的按鈕事件才能觸發這裡的方法
}
this._pDialog = Fragment.load(query).then(function (oDialog) {
// 關鍵:將 Dialog 掛載到 View 上,使其能共享 Model、i18n 與生命週期
oView.addDependent(oDialog);
return oDialog;
});
}

// 開啟 Dialog
this._pDialog.then(function (oDialog) {
oDialog.open();
});
},

// 點擊彈窗內「取消」按鈕
onCloseDialog: function () {
// 利用 id 找到 Dialog 並關閉它(它還會留在記憶體中,下次開啟很快)
this.byId("createPolicyDialog").close();
},

// 點擊彈窗內「儲存」按鈕
onSaveDialog: function () {
var sName = this.byId("inputCustomerName").getValue();
if (!sName) {
sap.m.MessageBox.error("保戶姓名為必填欄位!");
return;
}
// 執行後續儲存邏輯...
this.onCloseDialog(); // 儲存成功後關閉
}

});
});

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
2
3
4
5
6
<script id="sap-ui-bootstrap"
src="resources/sap-ui-core.js"
data-sap-ui-resource-roots='{
"my.navigation.app": "./"
}'>
</script>
這裡得到的線索:my.navigation.app 這個字串,就代表專案的根目錄(./,也就是 webapp 資料夾)。
2. 第二步:對照您的專案資料夾結構(目錄樹) webapp (根目錄,對應上方的 "./")
1
2
3
4
5
6
7
8
┣ controller
┃ ┗ Main.controller.js
┣ view
┃ ┣ fragment
┃ ┃ ┗ CreatePolicyDialog.fragment.xml <-- 假設這是您剛建好的彈窗檔案
┃ ┗ Main.view.xml
┣ index.html
┗ manifest.json
  • 核心技術重點複習(必記)
  • 為什麼不直接寫在 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
2
3
4
5
6
7
8
9
10
11
12
13
<mvc:View 
controllerName="myApp.controller.Main"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">

<Button
text="儲存資料"
icon="sap-icon://save"
type="Emphasized"
press="onSavePress" />

</mvc:View>

控制器 (Controller)

1
2
3
4
5
6
7
8
9
10
11
12
13
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast"
], function (Controller, MessageToast) {
"use block";

return Controller.extend("myApp.controller.Main", {
onSavePress: function (oEvent) {
// 當按鈕被點擊時執行的商務邏輯
MessageToast.show("資料已成功儲存!");
}
});
});
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
2
3
4
5
6
7
8
9
10
11
12
13
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:f="sap.ui.layout.form">
<f:SimpleForm editable="true">
<f:content>
<!-- 宣告 Label,並使用 labelFor 綁定到下方的 Input 控制項 -->
<Label text="使用者名稱" required="true" labelFor="usernameInput" />
<Input id="usernameInput" placeholder="請輸入您的姓名" />

<Label text="電子郵件" labelFor="emailInput" />
<Input id="emailInput" type="Email" />
</f:content>
</f:SimpleForm>
</mvc:View>

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([]);
    },
    });
    });