导航到带必需参数的路由
学习目标
导航到具有必需参数的路由
带必需参数的路由
假设当用户在初始视图上选择一个实体(例如客户、销售订单)时,应用程序要导航到另一个视图,在该视图中显示有关所选实体的详细信息。要实现这样的主从(master-detail)场景,你可以通过路由的一个或多个参数将所选实体的数据(例如关联的 Id)传递给明细视图。然后,明细视图可以使用该参数来标识实体,并获取和显示附加信息。
SAPUI5 支持带必需参数和可选参数的路由,二者都在路由的模式中定义。你通过将参数放在花括号中为模式指定必需参数。

在所示示例中,为 detail 路由定义了一个名为 customerId 的必需参数。这使得例如哈希 detail/5 和 detail/(00505604-4e85-1edd-818f-21e64b9cd2cf) 与该路由匹配,而哈希 detail/ 不匹配。随后,路由的 patternMatched 事件(参见下一节)会在其 arguments 参数中收到 5 或 (00505604-4e85-1edd-818f-21e64b9cd2cf) 作为 customerId。
参数处理
路由的参数使用路由器的 navTo 方法设置。在该方法中,在要导航到的路由名称之后,作为第二个参数传入一个包含该路由参数值的配置对象。
路由器始终确保路由模式中指定的必需参数已设置;否则会抛出错误。

在所示示例中,在初始视图的事件处理程序中调用路由器的 navTo 方法,以导航到名为 detail 的路由。该路由具有必需参数 customerId,其值通过作为第二个参数传入的对象提供。
在示例中,省略了如何确定客户 Id。例如,可以通过用户所选 UI 元素的绑定上下文来获取它。
使用所示的代码,浏览器的哈希会被设置为 detail/<value of customerId parameter>。
在导航到的视图中,现在必须再次提取传入的客户 Id,以便能够获取并显示有关该客户的附加信息。

在所示示例中,在明细视图控制器的 onInit 初始化方法中,通过路由器的 getRoute 方法查询 detail 路由的 Route 对象。在该对象上调用 attachPatternMatched 方法。这会将视图控制器的 _onObjectMatched 方法注册到路由的 patternMatched 事件。也就是说,当且仅当当前 URL 哈希与路由的模式匹配时,才会调用 _onObjectMatched 方法。在这种情况下,会在 _onObjectMatched 方法中提取 customerId 参数的值。
_onObjectMatched 事件处理程序方法的上下文(其 this)默认绑定到 detail 路由的 Route 对象。因此,会向 attachPatternMatched 方法传入视图控制器(this)作为第二个参数,以将 _onObjectMatched 方法的上下文绑定到视图控制器。这样,在 _onObjectMatched 方法的实现中就可以通过 this 访问视图控制器。
patternMatched 事件有一个名为 arguments 的参数。该参数是一个键值对对象,其中包含路由中定义的参数,并使用当前 URL 哈希中的相应信息进行解析。在 _onObjectMatched 方法的实现中,会访问该事件参数,并从中提取 customerId 参数的值。
在示例代码中,省略了如何继续处理所获取的 Id。例如,可以使用 this.getView().bindElement() 将视图的绑定上下文设置为所选客户,以显示有关该客户的附加信息。
导航到带必需参数的路由
业务场景
在之前的练习中,你已向该场景添加了从 Overview 视图到 Detail 视图的导航。但到目前为止,Detail 视图上未显示任何客户特定的数据。这将在本练习中实现:所选客户在 Overview 视图上的附加数据将显示在 Detail 视图上。
为此,你将首先向 Detail 视图的 UI 添加客户特定数据的字段。然后,你将向 detail 路由添加一个必需参数,并使用它在导航期间将 Overview 视图上所选客户的 Id 传递给 Detail 视图。最后,你将在明细视图控制器中使用传入的 Id 为 Detail 视图设置绑定上下文。这使得视图上使用的相对绑定路径能够被解析,并在视图上显示相应的客户数据。*模板:*Git Repository: https://github.com/SAP-samples/sapui5-development-learning-journey.git, Branch: **sol/25_invalid_hashes***参考答案:*Git Repository: https://github.com/SAP-samples/sapui5-development-learning-journey.git, Branch: sol/26_routing_with_parameters
任务 1:扩展 Detail 视图的 UI
步骤
在编辑器中打开
*i18n*文件夹中的*i18n.properties*资源束文件。将以下键值对添加到
*i18n.properties*文件,以便为下一步将添加的客户字段定义可翻译的标签:
customerNumberTitle=Customer Number
streetTitle=Street
postcodeTitle=Post Code
cityTitle=City
countryTitle=Country
emailTitle=Email
phoneTitle=Telephone
discountTitle=Discount
结果
i18n.properties
资源束文件现在应如下所示:
3. 在编辑器中打开 *webapp/view* 文件夹中的 *Detail.view.xml* 文件。
4. 将以下对象标题添加到 Page UI 元素的 content 聚合,以便在视图上显示包含客户特定数据的字段:
<ObjectHeader
responsive="true"
fullScreenOptimized="true"
title="{Form} {CustomerName}">
<attributes>
<ObjectAttribute title="{i18n>customerNumberTitle}" text="{CustomerNumber}"/>
<ObjectAttribute title="{i18n>streetTitle}" text="{Street}"/>
<ObjectAttribute title="{i18n>postcodeTitle}" text="{PostCode}"/>
<ObjectAttribute title="{i18n>cityTitle}" text="{City}"/>
<ObjectAttribute title="{i18n>countryTitle}" text="{Country}"/>
<ObjectAttribute title="{i18n>emailTitle}" text="{Email}"/>
<ObjectAttribute title="{i18n>phoneTitle}" text="{Telephone}"/>
<ObjectAttribute title="{i18n>discountTitle}" text="{ path: 'Discount',
type: 'sap.ui.model.type.Float',
formatOptions: {minFractionDigits: 2, maxFractionDigits: 2}
} %"/>
</attributes>
</ObjectHeader>
注意
这里使用相对路径来绑定客户字段。只要尚未设置该绑定的上下文,这些路径就无法被解析,因此无法显示任何数据。所以在接下来的步骤中,你将提供相应的绑定上下文。
结果
Detail 视图现在应如下所示:

任务 2:通过 detail 路由的必需参数将 Overview 视图上所选客户的 Id 传递给 Detail 视图
步骤
在编辑器中打开
*webapp*文件夹中的*manifest.json*应用描述符。在应用描述符中,找到
sap.ui5命名空间的路由配置部分中的routes属性:
"routes": [
{
"name": "overview",
"pattern": "",
"target": [
"overview"
]
},
{
"name": "detail",
"pattern": "detail",
"target": [
"detail"
]
}
]
将
detail路由中pattern属性的值更改为以下新值:
"pattern": "detail/{customerId}"
注意
这样,你就向 detail 路由添加了一个名为 customerId 的必需参数。该参数将在下一步中用于将 Overview 视图的客户表格中所选客户的 Id 传递给 Detail 视图。
结果
路由配置现在应如下所示:
4. 在编辑器中打开 *webapp/controller* 文件夹中的 *Overview.controller.js* 文件。
5. 按如下方式修改视图控制器中 onNavToDetails 事件处理程序的实现,以触发到 Detail 视图的导航,并用所选客户的 Id 填充上面定义的 detail 路由的 customerId 参数:
onNavToDetails: function (oEvent) {
var oItem = oEvent.getSource();
var oRouter = this.getOwnerComponent().getRouter();
oRouter.navTo("detail", {
customerId: oItem.getBindingContext().getPath().substring("/UX_Customer".length)
});
}
注意
添加到
onNavToDetails事件处理程序的oEvent参数用于查询触发press事件的控件。getSource方法返回客户表格中用户所选的那一行ColumnListItem对象。该项用于通过绑定获取关联客户的 Id。随后,获取到的 Id 会被设置为detail路由的customerId参数。例如,方法
oItem.getBindingContext().getPath()对于客户 SAP SE 会返回值/UX_Customer(00505604-4e85-1edd-818f-21e64b9cd2cf)。substring方法会从该字符串中移除/UX_Customer,并将(00505604-4e85-1edd-818f-21e64b9cd2cf)设置为customerId参数的值。这样,浏览器的哈希会被设置为detail/(00505604-4e85-1edd-818f-21e64b9cd2cf)。
结果
onNavToDetails 事件处理程序方法现在应如下所示:

任务 3:在 Detail 视图控制器中使用通过路由传入的客户 Id 为 Detail 视图设置绑定上下文
步骤
在编辑器中打开
*webapp/controller*文件夹中的*Detail.controller.js*文件。按如下方式实现视图控制器的
onInit初始化方法,以将_onObjectMatched方法注册为detail路由的patternMatched事件的事件处理程序:
onInit: function () {
var oRouter = this.getOwnerComponent().getRouter();
oRouter.getRoute("detail").attachPatternMatched(this._onObjectMatched, this);
}
注意
_onObjectMatched 方法将在下一步中实现。通过在此处注册它,当当前 URL 哈希与 detail 路由的模式匹配时,它将自动被调用。
结果
视图控制器现在应如下所示:
3. 按如下方式实现 _onObjectMatched 方法,以为 Detail 视图上的绑定设置上下文:
_onObjectMatched: function (oEvent) {
this.getView().bindElement("/UX_Customer" + oEvent.getParameter("arguments").customerId);
}
注意
_onObjectMatched 事件处理程序方法的 oEvent 参数用于查询 Overview 视图控制器中为 detail 路由的 customerId 参数设置的值(例如 (00505604-4e85-1edd-818f-21e64b9cd2cf))。由此创建相应客户的绑定路径(例如 /UX_Customer(00505604-4e85-1edd-818f-21e64b9cd2cf)),并通过 bindElement 方法将其设置为 Detail 视图的绑定上下文。现在,Detail 视图上的所有相对绑定都可以被解析,并且可以在视图上显示相应的客户数据。
结果
视图控制器现在应如下所示:
4. 通过从 SAP Business Application Studio 启动应用程序来进行测试运行。
警告
如果你未连接到后端系统,请使用 start-mock npm 脚本启动应用程序。 确保 Detail 视图现在显示 Overview 视图表格中所选客户的数据。
右键单击你的 sapui5-development-learning-journey 项目中的任意子文件夹,然后在出现的上下文菜单中选择 Preview Application。
在出现的对话框中选择名为 start-mock 的 npm 脚本。
在打开的应用程序中,检查组件是否按预期工作。