创建自定义控件
学习目标
使用 SAPUI5 框架实现自定义控件。
自定义控件
开发您自己的控件
有时,需求会超出扩展现有控件的可能性范围。在其他情况下,需要通过组合现有控件来实现可复用的自定义控件。使用 SAPUI5,还可以实现您自己的客户特定控件,即所谓的自定义控件。在本课中,您将学习如何实现此类自定义控件。
创建自定义控件
当您能够扩展现有控件时,创建自定义控件其实并没有太大区别。创建自定义控件时,您只需改变该控件所扩展的对象,然后必须完全自行实现渲染器。
观看本视频以了解更多信息。
视频:本节含 SAP 官方视频(视频 ID
1_7c1rbc75),需在 learning.sap.com 在线观看。
控件与元素
如您所知,SAPUI5 提供的不仅仅是基本控件。此外,SAPUI5 框架确实提供了更复杂的控件,它们与其他控件存在依赖关系。该框架还具有称为元素的视觉方面的对象。SAPUI5 中的元素不能单独使用,必须与控件结合使用。它们处于父子依赖关系中。该关系中的控件是父级,元素是子级。例如,父级知道如何在运行时显示或渲染子级。
以下规则适用于元素:
sap.ui.core.Element 是 sap.ui.core.Control 的基类
它有 API,但没有渲染器。
它不适合单独使用。
通常,它由某个控件聚合(例如 Menu 中的 MenuItems)。
控件负责渲染,并将 Element 用作数据容器。
Element 是 UI5 UI 最基本的构建块。Element 具有像 ManagedObject 那样的状态,并且有一个唯一 ID,框架通过该 ID 记住它。它可以有关联的 DOM,但不能自行渲染。只有 Controls 可以自行渲染,并且还负责渲染它们作为子级聚合的 Elements。如果 Element 已被渲染,其相关 DOM 会获得与 Element 相同的 ID,从而可以通过 API 获取。
使用元素
下图向您展示如何在聚合绑定期间使用元素。

下图所示代码向您展示控件与元素的实现及其关系。

下图所示代码向您展示如何访问 PersonItem 元素的列表。

创建自定义控件
业务示例
在本练习中,您将通过添加一个自定义控件来扩展 fullscreen 应用程序。该控件显示 Flights 表中有关飞机的数据,包括以下内容:
最大乘客数
当前已预订的乘客数
如下图所示:

注意
SAP Business Technology Platform 及其工具是云服务。由于云软件的特性,步骤流程以及字段和按钮的命名可能与练习解决方案有所不同。
前提条件
您需要已完成先前关于实现全屏应用程序的练习。解决方案展示的是完成扩展控件练习之后的应用程序,但该部分对于下面的练习并不需要。
注意
如果您愿意,可以下载解决方案中的 1-Fullscreen complete.tar 或 3-controlextend.tar 文件作为起点。
任务 1:创建自定义控件
步骤
打开 SAP Business Application Studio。
在 fullscreen(或 controlextend)项目的 control 文件夹中,创建一个名为
PlaneInfo.js的新文件。按先前练习中所示执行此步骤。
在
*PlaneInfo.js*文件中,通过扩展sap.ui.core.Control创建一个名为PlaneInfo的自定义控件。使用以下代码:
sap.ui.define([
"sap/ui/core/Control"
],
function (Control) {
"use strict";
return Control.extend("student.com.sap.training.advancedsapui5.fullscreen.control.PlaneInfo", {
});
}
);
添加元数据部分。将以下
properties添加到元数据定义中,并将给定的类型赋给type属性。然后保存您的更改。
PlaneInfo.js 文件元数据部分中的属性
属性 |
类型 |
|---|---|
seatsMax |
string |
seatsOcc |
string |
在
extend函数内输入以下代码:
metadata:{
properties: {
"seatsMax" : {
type: "string"
},
"seatsOcc" : {
type: "string"
}
}
}
保存您的更改。
任务 2:实现渲染器
必须为 PlaneInfo 控件实现渲染器。该渲染器遵循渲染器的命名规范。
步骤
在 fullscreen(或 controlextend)项目的 control 文件夹中,创建一个名为
PlaneInfoRenderer.js的新文件。按先前练习中所示执行此步骤。
在
*PlaneInfoRenderer.js*文件中,通过扩展基类sap.ui.core.Renderer创建一个名为PlaneInfoRenderer的自定义控件,将扩展后的对象赋给名为PlaneInfoRenderer的变量,并将创建的对象返回给调用方。使用以下代码:
sap.ui.define([
"sap/ui/core/Renderer"
],
function (Renderer) {
"use strict";
var PlaneInfoRenderer = Renderer.extend("student.com.sap.training.advancedsapui5.fullscreen.control.PlaneInfoRenderer");
return PlaneInfoRenderer;
}
);
要启用类似增量 DOM 的 API,请将
PlaneInfoRenderer对象的apiVersion设置为2。在
return PlaneInfoRenderer语句之前添加以下代码:
PlaneInfoRenderer.apiVersion = 2;
向步骤 2 中创建的
PlaneInfoRenderer对象添加一个render函数。该函数接受两个参数。将第一个参数命名为oRm。它在运行时将包含对 RenderManager 的引用。将第二个参数命名为oControl。该变量将包含对渲染器应渲染的控件的引用。向render函数添加代码以渲染该控件。HTML 表格控件应包含来自 PlaneInfo 控件属性seatsMax和seatsOcc的三行数据。此时不要加入图标(如练习开始时所示)。现在,保存您的更改。
提示
正在渲染的表格是 HTML 表格,而不是 SAPUI5 表格。可以通过自动生成的 getter 方法,从传入的 oControl 对象访问 PlaneInfo 控件的数据。
使用传入的 RenderManager 写出一个起始 div,并为传入的
oControl对象写出控件数据。使用 RenderManager 的openStart函数。写出一个 HTML 表格控件,其中包含来自 PlaneInfo 控件属性
seatsMax和seatsOcc的三行数据。此时不要加入图标(如练习开始时所示)。使用 RenderManager 的openStart、openEnd、close、attr和text函数。关闭表格和 div。使用 RenderManager 的
close函数。实现应如下代码所示:
PlaneInfoRenderer.render = function(oRm, oControl) {
oRm.openStart("div",oControl);
oRm.openEnd();
oRm.openStart("table");
oRm.attr("align", "center");
oRm.openEnd();
oRm.openStart("tr");
oRm.openEnd();
oRm.openStart("td");
oRm.openEnd();
oRm.text(" "+oControl.getSeatsMax());
oRm.close("td");
oRm.close("tr");
oRm.openStart("tr");
oRm.openEnd();
oRm.openStart("td");
oRm.openEnd();
oRm.text(" "+oControl.getSeatsOcc());
oRm.close("td");
oRm.close("tr");
oRm.close("table");
oRm.close("div");
}
注意
为减少代码量,您可以使用方法链。
保存您的更改。
任务 3:将 PlaneInfoRenderer 添加到 PlaneInfo 控件
步骤
打开
*PlaneInfo.js*文件,并在实现中添加对新PlaneInfoRenderer的引用。打开项目 control 文件夹中的
*PlaneInfo.js*文件。按如下方式更新代码:
sap.ui.define([
"sap/ui/core/Control",
"student/com/sap/training/advancedsapui5/fullscreen/control/PlaneInfoRenderer"
],
function (Control, PlaneInfoRenderer) {
"use strict";
向实现中添加一个属性
renderer,并将PlaneInfoRenderer引用赋给它。在元数据定义之后添加以下代码:
,
renderer: PlaneInfoRenderer
保存您的更改。
任务 4:将 PlaneInfo 控件添加到应用程序
步骤
打开
*i18n.properties*文件,并添加以下键值对。现在,保存您的更改。
i18n.properties 文件中的键值对
键 |
值 |
|---|---|
planeInfo |
Plane Infos |
按先前练习中所示执行此步骤。
打开
*Flights.view.xml*文件。在最后一个Column元素之前,向columns聚合添加一个新的支持移动设备的Column元素,其属性如下:
Flights.view.xml 文件中 Column 元素的属性值对
属性 |
值 |
|---|---|
id |
|
minScreenWidth |
|
demandPopin |
|
hAlign |
|
打开
*Flights.view.xml*文件。在
flseatocccolumn和flbooking元素之间添加以下代码:
<Column id="flplaneinfo" minScreenWidth="Tablet" demandPopin="true" hAlign="Center">
</Column>
向新建的
Column元素添加一个sap.m.Text元素,其属性和值如下:
Flights.view.xml 文件中 Text 元素的属性值对
属性 |
值 |
|---|---|
id |
|
text |
|
在新的 Column 定义内添加以下代码:
<Text id="flplaneinfotext" text="{i18n>planeInfo}"/>
在
cells聚合的HoverButton元素之前,添加一个PlaneInfo元素,其属性和值如下。请注意,PlaneInfo位于项目特定的命名空间中。现在,保存您的更改。
Flights.view.xml 文件中 PlaneInfo 元素的属性值对
属性 |
值 |
|---|---|
seatsMax |
|
seatsOcc |
|
id |
|
在
cells聚合中、HoverButton定义之前添加以下代码:
<cust:PlaneInfo id="planeInfo1"
seatsMax="{Seatsmax}"
seatsOcc="{Seatsocc}"
/>
保存您的更改。
运行应用程序。
注意
请注意,由于我们不是在真实的 SAP Fiori 环境中测试应用程序,如果您使用开发者工具调试应用程序,控制台中会出现错误。请忽略任何关于资源预加载的消息。
按先前练习中所示执行此步骤。
验证 Flights 表中的行现在是否显示带有这三项数据的
PlaneInfo控件。如果控件未显示或应用程序加载失败,请打开 Chrome DevTools 并查看生成的 HTML 代码。
在 Carriers 表中选择一个承运人。
验证 Flights 表中的行现在是否显示带有这三项数据的
PlaneInfo控件。根据需要调整 PlaneInfoRenderer.js 文件以使 HTML 正确。根据需要,使用 Chrome DevTools 查看自定义控件插入的 HTML 代码。这可能需要多次尝试。
任务 5:向 PlaneInfo 控件添加图标
步骤
打开
*PlaneInfoRenderer.js*文件。按先前练习中所示执行此步骤。
为清楚表明这些数字的含义,请在
PlaneInfo表格的数字之前添加图标。在适当的位置显示所列图标。使用 RenderManager 的icon函数。它以图标的 URL 作为参数。SAP 图标的 URL 前缀是sap-icon://。
PlaneInfoRenderer.js 文件中的图标
图标 |
位于其前 |
|---|---|
|
seatsMax |
|
seatsOcc |
打开
*PlaneInfoRenderer.js*文件。在
oRm.text(" "+oControl.getSeatsMax());之前添加以下代码:
oRm.icon("sap-icon://person-placeholder");
在
oRm.text(" "+oControl.getSeatsOcc());之前添加以下代码:
oRm.icon("sap-icon://suitcase");
运行应用程序。
按先前练习中所示执行此步骤。
验证图标是否显示在 PlaneInfo 控件上。您可能需要在图标后添加几个空格,使数字稍微远离图标。

在 Carriers 表中选择一个承运人。
验证图标是否显示在 PlaneInfo 控件上。
您现在可以关闭运行应用程序的浏览器标签页。
由于我们将在后续练习中进一步开发您的 fullscreen 项目,您可以通过下载来保存项目的当前状态。选择 fullscreen 项目,并从上下文菜单中选择 Download。