酒店预订示例:集合渲染器覆盖列表输出
本示例展示如何使用集合渲染器(Collection Renderer)——这是一种自定义列表项显示方式的模式。与航班示例中使用的顶级 renderer/editor 覆盖不同,集合渲染器控制列表中每一项的渲染方式。我们将使用 HotelReservation Apex 类查找可用酒店,然后创建 hotelResponse 自定义 Lightning Type,将酒店列表渲染为精美的卡片。
Apex 类设计
HotelReservation — 主 InvocableMethod
- @InvocableMethod(label='Find hotels' description='Find Available Hotels')
- 输入:HotelRequest(city、checkInDate、checkOutDate)—— 三个简单字段
- 输出:HotelResponse → List<Hotel> —— 关键区别:输出是列表
数据类结构
| 类 | 字段 |
|---|---|
| Hotel | name (String), address (String), rooms (List<Room>), hotelCategory (HotelCategory) |
| Room | type (String), available (Integer), discountPercentage (Double), price (Long), petAllowed (Boolean) |
| HotelCategory | star (String) — 如 "four"、"five" |
| HotelRequest | city (String), checkInDate (Date), checkOutDate (Date) |
示例硬编码两家酒店(生产环境应从外部服务获取):Sahara Hotels(四星,Gacchibowli Hyderabad,DELUX 房间 $2000,15.15% 折扣)和 Taj Vivanta(五星,Kokapet,DELUX 房间 $2000,15.15% 折扣)。
默认 UI 和结果数据
创建 Agent Action
- 方法:Find hotels
- 输入:checkInDate (dateType), checkOutDate (dateType), city (textType)
- 输出:hotels — list 类型,使用 @apexClassType/c__Hotel
默认输出问题
原始 JSON 无格式显示——酒店名称、地址、星级、房间信息全部混杂在一起,无法快速浏览和比较酒店选项:
{"hotels": [
{"name": "Sahara Hotels", "address": "Gacchibowli Hyderabad",
"hotelCategory": {"star": "four"},
"rooms": [{"type": "DELUX", "price": 2000, "discountPercentage": 15.15, "available": 2}]
},
{"name": "Taj Vivanta", "address": "Kokapet",
"hotelCategory": {"star": "five"},
"rooms": [/* 同上结构 */]
}
]}
目标:创建 hotelResponse CLT,使用集合渲染器将每个酒店显示为带样式的卡片。
自定义输出:hotelResponse CLT
目录结构
lightningTypes/
hotelResponse/
schema.json
lightningDesktopGenAi/
renderer.json
schema.json
引用单个 Hotel 的 Apex 类类型(而非列表):
{
"title": "Hotel Reservation",
"description": "Hotel Reservation",
"lightning:type": "@apexClassType/c__Hotel"
}
renderer.json — 集合渲染器(与航班示例的关键区别)
使用 "collection" 键包裹 componentOverrides,告诉系统对列表中的每个单独项目应用 LWC:
{
"collection": {
"renderer": {
"componentOverrides": {
"$": {
"definition": "c/hotelDetails"
}
}
}
}
}
两种覆盖模式对比
| 模式 | 渲染器结构 | 适用场景 |
|---|---|---|
| 顶级 Renderer (航班示例) | "renderer": {"componentOverrides": {...}} | 覆盖整个输出组件 |
| 集合 Renderer (酒店示例) | "collection": {"renderer": {"componentOverrides": {...}}} | 覆盖列表中每一项的渲染方式。LWC 每次接收一个列表项 |
LWC:hotelDetails 组件
- Target:
lightning__AgentforceOutput - sourceType:
lightning__listType,itemTypeName="c__hotelResponse" - HTML 布局:lightning-card "Available Hotels" 带旅行图标 —— 迭代 {value} 数组 —— 每个酒店:名称 + 位置图标 + 地址 —— 每个房间:类型、可用数量、宠物政策、价格(₹)、折扣标签
- JS:极简 —— 仅
@api value(组件通过 value 属性接收数据)
关键区别:集合渲染器中的 LWC 接收 单个列表项(而非整个列表),通过 @api value 属性。这使得每个酒店都能获得一致的卡片样式。
集成和最终效果
集成步骤
- 打开 Agent Action → 编辑 HotelResponse 的 Output Rendering 参数
- 选择 hotelResponse 自定义 Lightning Type
- 保存(忽略 "Unsupported Data Type" 提示)
- 测试前重新加载 Agent 页面
改造前(默认 UI)
- 原始 JSON —— 酒店名称、地址、星级和房间信息全部混杂
- 无视觉卡片、无图标、无结构
- 无法快速比较酒店
改造后(hotelResponse CLT)
- "Available Hotels" 卡片 + 旅行图标标题
- 每个酒店以独立样式卡片展示:酒店名称(标题)+ 位置图标 + 地址
- 每个房间在阴影子框中展示:房型(粗体标题)、可用数量(事件图标)、宠物政策(动物图标)、价格(₹ 突出显示)、折扣百分比(标签/芯片)
- 干净、专业、可快速浏览的布局
三种覆盖模式最终总结
| 模式 | renderer.json 结构 | 适用场景 |
|---|---|---|
| 顶级 Renderer | {"renderer": {"componentOverrides": {"$": {"definition": "c/xxx"}}}} | 覆盖整个输出显示(航班示例) |
| 集合 Renderer | {"collection": {"renderer": {"componentOverrides": {"$": {"definition": "c/xxx"}}}}} | 覆盖列表中每项渲染——LWC 接收单个项(酒店示例) |
| 顶级 Editor | {"editor": {"componentOverrides": {"$": {"definition": "c/xxx"}}}} | 覆盖输入表单显示(航班 Filter 示例) |
集合渲染器是列表输出的核心模式 —— 它将每个列表项作为独立卡片渲染,配合顶级 Renderer 和 Editor 模式,组成了 Custom Lightning Types UI 自定义的完整工具箱。