上一章讲了 Fiori开发的 Routing with Parameters(带参数的路由)和 Routing Back and History(路由返回和履历)。
SAP学习笔记 - 开发28 - 前端Fiori开发 Routing with Parameters(带参数的路由)和 Routing Back and History(路由返回和履历)-CSDN博客
本章继续讲 Fiori 开发的知识。
目录
[1,Custom Controls(自定义控件)](#1,Custom Controls(自定义控件))
[b,Metadata 定义](#b,Metadata 定义)
[c,init() 方法](#c,init() 方法)
[h,renderer(oRm, oControl)](#h,renderer(oRm, oControl))
下面是详细内容。
1,Custom Controls(自定义控件)
有关控件,咱们之前也大概说过。懂 HTML,Windows Form,Javascript 等等的朋友肯定秒懂
大概就是一个黑盒子,实现一定的功能,暴露一些属性给用户这么一个东西。
SAP学习笔记 - 开发15 - 前端Fiori开发 Boostrap,Controls,MVC(Model,View,Controller),Modules-CSDN博客
Fiori 本身提供了大量的控件,咱们这里说的是自定义控件。下面通过实例来看看是怎么做的。
当然这里先说一下咱们这个控件的要件:
-
控件标题
-
评星 + Thank you Message + 打分按钮
-
点击打分按钮之后,会提示一个评分结果Toast Message

下面来看要哪些文件。
1),ProductRating.js
Fiori 自定义控件至少需要如下属性,metadata,init,renderer
javascript
sap.ui.define([
"sap/ui/core/Control"
], (Control) => {
"use strict";
return Control.extend("ui5.walkthrough.control.ProductRating", {
metadata : {},
init() {},
renderer(oRM, oControl) {}
});
});
这里直接给出实现
javascript
sap.ui.define([
"sap/ui/core/Control",
"sap/m/RatingIndicator",
"sap/m/Label",
"sap/m/Button"
], (Control, RatingIndicator, Label, Button) => {
"use strict";
return Control.extend("ui5.walkthrough.control.ProductRating", {
metadata : {
properties : {
value: {type : "float", defaultValue : 0}
},
aggregations : {
_rating : {type : "sap.m.RatingIndicator", multiple: false, visibility : "hidden"},
_label : {type : "sap.m.Label", multiple: false, visibility : "hidden"},
_button : {type : "sap.m.Button", multiple: false, visibility : "hidden"}
},
events : {
change : {
parameters : {
value : {type : "int"}
}
}
}
},
init() {
this.setAggregation("_rating", new RatingIndicator({
value: this.getValue(),
iconSize: "2rem",
visualMode: "Half",
liveChange: this._onRate.bind(this)
}));
this.setAggregation("_label", new Label({
text: "{i18n>productRatingLabelInitial}"
}).addStyleClass("sapUiSmallMargin"));
this.setAggregation("_button", new Button({
text: "{i18n>productRatingButton}",
press: this._onSubmit.bind(this)
}).addStyleClass("sapUiTinyMarginTopBottom"));
},
setValue(fValue) {
this.setProperty("value", fValue, true);
this.getAggregation("_rating").setValue(fValue);
return this;
},
reset() {
const oResourceBundle = this.getModel("i18n").getResourceBundle();
this.setValue(0);
this.getAggregation("_label").setDesign("Standard");
this.getAggregation("_rating").setEnabled(true);
this.getAggregation("_label").setText(oResourceBundle.getText("productRatingLabelInitial"));
this.getAggregation("_button").setEnabled(true);
},
_onRate(oEvent) {
const oRessourceBundle = this.getModel("i18n").getResourceBundle();
const fValue = oEvent.getParameter("value");
this.setProperty("value", fValue, true);
this.getAggregation("_label").setText(oRessourceBundle.getText("productRatingLabelIndicator", [fValue, oEvent.getSource().getMaxValue()]));
this.getAggregation("_label").setDesign("Bold");
},
_onSubmit(oEvent) {
const oResourceBundle = this.getModel("i18n").getResourceBundle();
this.getAggregation("_rating").setEnabled(false);
this.getAggregation("_label").setText(oResourceBundle.getText("productRatingLabelFinal"));
this.getAggregation("_button").setEnabled(false);
this.fireEvent("change", {
value: this.getValue()
});
},
renderer(oRm, oControl) {
oRm.openStart("div", oControl);
oRm.class("myAppDemoWTProductRating");
oRm.openEnd();
oRm.renderControl(oControl.getAggregation("_rating"));
oRm.renderControl(oControl.getAggregation("_label"));
oRm.renderControl(oControl.getAggregation("_button"));
oRm.close("div");
}
});
});
注意一下这个文件是在 control 文件夹下面的,不是controller 文件夹
a,导入这4个模块儿
-
Control: 所有自定义控件的基类
-
RatingIndicator: 提供星级评分功能
-
Label: 显示文本标签
-
Button: 提供提交按钮
b,Metadata 定义
- properties:
value: 表示当前评分值,类型为float,默认值为0
- aggregations:
_rating: 内部使用的RatingIndicator控件
_label: 内部使用的Label控件
_button: 内部使用的Button控件
所有聚合都设置为visibility: "hidden",表示它们是内部实现细节
- events:
change: 当提交评分时触发,携带评分值作为参数
javascript
metadata : {
properties : {
value: {type : "float", defaultValue : 0}
},
aggregations : {
_rating : {type : "sap.m.RatingIndicator", multiple: false, visibility : "hidden"},
_label : {type : "sap.m.Label", multiple: false, visibility : "hidden"},
_button : {type : "sap.m.Button", multiple: false, visibility : "hidden"}
},
events : {
change : {
parameters : {
value : {type : "int"}
}
}
}
}
c,init() 方法
初始化内部控件:
_rating: 创建RatingIndicator,设置初始值、图标大小、视觉模式(半星)和liveChange事件处理程序
_label: 创建Label,设置初始文本(从i18n资源获取)并添加CSS类
_button: 创建Button,设置文本(从i18n资源获取)、press事件处理程序并添加CSS类
javascript
init() {
this.setAggregation("_rating", new RatingIndicator({
value: this.getValue(),
iconSize: "2rem",
visualMode: "Half",
liveChange: this._onRate.bind(this)
}));
this.setAggregation("_label", new Label({
text: "{i18n>productRatingLabelInitial}"
}).addStyleClass("sapUiSmallMargin"));
this.setAggregation("_button", new Button({
text: "{i18n>productRatingButton}",
press: this._onSubmit.bind(this)
}).addStyleClass("sapUiTinyMarginTopBottom"));
}
d,setValue(fValue)
-
设置评分值并同步更新RatingIndicator的值
-
返回this以支持方法链式调用
javascript
setValue(fValue) {
this.setProperty("value", fValue, true);
this.getAggregation("_rating").setValue(fValue);
return this;
}
e,reset()
- 重置控件状态:
评分值设为0
标签设计恢复为"Standard"
启用RatingIndicator
恢复标签初始文本
启用按钮
javascript
reset() {
const oResourceBundle = this.getModel("i18n").getResourceBundle();
this.setValue(0);
this.getAggregation("_label").setDesign("Standard");
this.getAggregation("_rating").setEnabled(true);
this.getAggregation("_label").setText(oResourceBundle.getText("productRatingLabelInitial"));
this.getAggregation("_button").setEnabled(true);
}
f,_onRate(oEvent)
-
RatingIndicator的liveChange事件处理程序
-
更新当前值
-
设置标签文本显示当前评分和最大评分值
-
将标签文本加粗
javascript
_onRate(oEvent) {
const oRessourceBundle = this.getModel("i18n").getResourceBundle();
const fValue = oEvent.getParameter("value");
this.setProperty("value", fValue, true);
this.getAggregation("_label").setText(oRessourceBundle.getText("productRatingLabelIndicator", [fValue, oEvent.getSource().getMaxValue()]));
this.getAggregation("_label").setDesign("Bold");
}
g,_onSubmit(oEvent)
-
按钮的press事件处理程序
-
禁用RatingIndicator
-
设置标签文本为最终状态
-
禁用按钮
-
触发change事件,传递当前评分值
javascript
_onSubmit(oEvent) {
const oResourceBundle = this.getModel("i18n").getResourceBundle();
this.getAggregation("_rating").setEnabled(false);
this.getAggregation("_label").setText(oResourceBundle.getText("productRatingLabelFinal"));
this.getAggregation("_button").setEnabled(false);
this.fireEvent("change", {
value: this.getValue()
});
}
h,renderer(oRm, oControl)
- 定义控件的HTML结构:
创建一个div容器,添加自定义CSS类
依次渲染RatingIndicator、Label和Button控件
关闭div容器
javascript
renderer(oRm, oControl) {
oRm.openStart("div", oControl);
oRm.class("myAppDemoWTProductRating");
oRm.openEnd();
oRm.renderControl(oControl.getAggregation("_rating"));
oRm.renderControl(oControl.getAggregation("_label"));
oRm.renderControl(oControl.getAggregation("_button"));
oRm.close("div");
}
i,总结
这个自定义控件ProductRating提供了一个完整的产品评分功能,包括:
星级评分(RatingIndicator)
动态显示的评分文本(Label)
提交按钮(Button)
完整的交互逻辑和状态管理
控件设计良好,使用了SAPUI5的最佳实践,包括:
清晰的元数据定义
内部聚合的封装(visibility: hidden)
国际化支持(i18n)
自定义事件
方法链式调用
响应式设计
这个控件可以很容易地在其他SAP Fiori应用中使用,通过value属性设置初始值,监听change事件获取用户提交的评分。

2),Detail.view.xml
javascript
<mvc:View
controllerName="ui5.walkthrough.controller.Detail"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:wt="ui5.walkthrough.control">
<Page
title="{i18n>detailPageTitle}"
showNavButton="true"
navButtonPress=".onNavBack">
<ObjectHeader
intro="{invoice>ShipperName}"
title="{invoice>ProductName}"/>
<wt:ProductRating
id="rating"
class="sapUiSmallMarginBeginEnd"
change=".onRatingChange"/>
</Page>
</mvc:View>
- 用 wt (自定义命名空间) 引用之前定义的产品评分控件
<wt:ProductRating
id="rating"
class="sapUiSmallMarginBeginEnd"
change=".onRatingChange"/>
3),Detail.controller.js
javascript
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/routing/History",
"sap/m/MessageToast"
], (Controller, History, MessageToast) => {
"use strict";
return Controller.extend("ui5.walkthrough.controller.Detail", {
...
onObjectMatched(oEvent) {
this.byId("rating").reset();
this.getView().bindElement({
path: "/" + window.decodeURIComponent(oEvent.getParameter("arguments").invoicePath),
model: "invoice"
});
},
onNavBack() {
const oHistory = History.getInstance();
const sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
const oRouter = this.getOwnerComponent().getRouter();
oRouter.navTo("overview", {}, true);
}
},
onRatingChange(oEvent) {
const fValue = oEvent.getParameter("value");
const oResourceBundle = this.getView().getModel("i18n").getResourceBundle();
MessageToast.show(oResourceBundle.getText("ratingConfirmation", [fValue]));
}
});
});
a,onRatingChange(oEvent)
功能:处理评分变化的回调
逻辑:
从事件中获取评分值(value)
获取国际化资源包,显示评分确认消息:
使用i18n.properties 中的"ratingConfirmation"消息模板,将评分值(fValue)作为参数插入消息
触发:当用户在ProductRating控件中提交评分时调用
UI反馈:通过MessageToast显示短暂的消息提示
javascript
onRatingChange(oEvent) {
const fValue = oEvent.getParameter("value");
const oResourceBundle = this.getView().getModel("i18n").getResourceBundle();
MessageToast.show(oResourceBundle.getText("ratingConfirmation", [fValue]));
}

4),style.css
css
html[dir="ltr"] .myAppDemoWT .myCustomButton.sapMBtn {
margin-right: 0.125rem
}
html[dir="rtl"] .myAppDemoWT .myCustomButton.sapMBtn {
margin-left: 0.125rem
}
.myAppDemoWT .myCustomText {
display: inline-block;
font-weight: bold;
}
/* ProductRating */
.myAppDemoWTProductRating {
padding: 0.75rem;
}
.myAppDemoWTProductRating .sapMRI {
vertical-align: initial;
}

5),i18n.properties
html
# App Descriptor
appTitle=Hello World
appDescription=A simple walkthrough app that explains the most important concepts of SAPUI5
# Hello Panel
showHelloButtonText=Say Hello
helloMsg=Hello {0}
homePageTitle=Walkthrough
helloPanelTitle=Hello World
openDialogButtonText=Say Hello With Dialog
dialogCloseButtonText=Ok
# Invoice List
invoiceListTitle=Invoices
invoiceStatusA=New
invoiceStatusB=In Progress
invoiceStatusC=Done
# Detail Page
detailPageTitle=Walkthrough - Details
ratingConfirmation=You have rated this product with {0} stars
# Product Rating
productRatingLabelInitial=Please rate this product
productRatingLabelIndicator=Your rating: {0} out of {1}
productRatingLabelFinal=Thank you for your rating!
productRatingButton=Rate

6),运行看效果

点任意一条,到明细画面,就能看到咱们做的那个控件啦

点一下星评,后面 "Please reate this product" 就变成了 "Your rating: 3 out of 5",评3星嘛

点 Rate 按钮,出来一个Toast Message

以上就是本篇的全部内容。
更多SAP顾问业务知识请点击下面目录链接或东京老树根的博客主页