SAP学习笔记 - 开发29 - 前端Fiori开发 Custom Controls(自定义控件)

上一章讲了 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(自定义控件))

1),ProductRating.js

a,导入这4个模块儿

[b,Metadata 定义](#b,Metadata 定义)

[c,init() 方法](#c,init() 方法)

d,setValue(fValue)

e,reset()

f,_onRate(oEvent)

g,_onSubmit(oEvent)

[h,renderer(oRm, oControl)](#h,renderer(oRm, oControl))

i,总结

2),Detail.view.xml

3),Detail.controller.js

a,onRatingChange(oEvent)

4),style.css

5),i18n.properties

6),运行看效果


下面是详细内容。

1,Custom Controls(自定义控件)

SAPUI5 SDK - Demo Kit

有关控件,咱们之前也大概说过。懂 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顾问业务知识请点击下面目录链接或东京老树根的博客主页

https://blog.csdn.net/shi_ly/category_12216766.html

东京老树根-CSDN博客

相关推荐
Chef_Chen1 分钟前
从0开始学习R语言--Day39--Spearman 秩相关
开发语言·学习·r语言
阿絮~1 小时前
Apache RocketMQ进阶之路阅读笔记和疑问
笔记·apache·rocketmq
天水幼麟6 小时前
动手学深度学习-学习笔记(总)
笔记·深度学习·学习
天水幼麟8 小时前
动手学深度学习-学习笔记【二】(基础知识)
笔记·深度学习·学习
绿皮的猪猪侠9 小时前
算法笔记上机训练实战指南刷题
笔记·算法·pta·上机·浙大
沧海一笑-dj9 小时前
【51单片机】51单片机学习笔记-课程简介
笔记·学习·51单片机·江科大·江科大学习笔记·江科大单片机·江科大51单片机
老虎06279 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
大苏打seven10 小时前
Docker学习笔记:Docker网络
笔记·学习·docker
Green1Leaves12 小时前
pytorch学习-9.多分类问题
人工智能·pytorch·学习
慕y27412 小时前
Java学习第十五部分——MyBatis
java·学习·mybatis