第 3 章:自定义看板视图¶
我们已经了解了网页框架提供的各种功能。下一步,我们将自定义一个看板视图。这是一个更为复杂的项目,将展示框架的一些非显而易见的方面。目标是练习组合视图、协调用户界面的各个方面,并以一种可维护的方式进行操作。
巴芬想到了一个绝妙的主意:将看板视图和列表视图结合,会完全满足你的需求!简而言之,他希望在 CRM 看板视图的左侧显示一个客户列表。当你点击左侧侧边栏中的某个客户时,右侧的看板视图会过滤,仅显示与该客户相关的潜在客户。
目标

每个章节练习的解决方案都托管在 官方 Odoo 教程仓库 中。
1. 创建新的看板视图¶
既然我们正在自定义看板视图,那么让我们首先对其进行扩展,并在CRM的看板视图中使用我们的扩展。
创建一个新空组件,该组件继承自
@web/views/kanban/kanban_controller
中的KanbanController
组件。创建一个新的视图对象,并从
@web/views/kanban/kanban_view
中的kanbanView
赋予所有键和值。通过放置你新创建的控制器来覆盖 Controller 键。将其注册到视图注册表中,使用
awesome_kanban
。在
awesome_kanban/views/views.xml
文件中更新 CRM 看板的 arch,以使用扩展视图。可以通过在看板节点中指定js_class
属性来实现。
2. 创建一个 CustomerList 组件¶
我们将需要显示一个客户列表,所以不妨创建这个组件。
创建一个
CustomerList
组件,目前仅显示一个带有文本的div
。它应该有一个
selectCustomer
属性。创建一个新的模板,通过 XPath 继承
web.KanbanView
看板控制器模板,以在看板渲染器旁边添加CustomerList
。目前为其提供一个空函数作为selectCustomer
。小技巧
你可以在模板中使用此 xpath 在渲染组件之前添加一个 div。
<xpath expr="//t[@t-component='props.Renderer']" position="before"> ... </xpath>
在子组件中添加
CustomerList
的看板控制器子类。确保你在看板视图中看到你的组件。

另请参见
3. 加载并显示数据¶
将
CustomerList
组件修改为在onWillStart
中获取所有客户的列表。在模板中使用
t-foreach
显示列表。每当选择一个客户时,调用
selectCustomer
函数属性。

4. 更新主看板视图¶
在看板控制器中实现
selectCustomer
以添加适当的 domain。小技巧
由于与搜索视图交互并不简单,这里提供一个代码片段来创建筛选器:
this.env.searchModel.createNewFilters([{ description: partner_name, domain: [["partner_id", "=", partner_id]], isFromAwesomeKanban: true, // this is a custom key to retrieve our filters later }])
通过点击多个客户,您会发现旧的客户筛选器并未被替换。请确保在点击某个客户时,旧的筛选器会被新的筛选器替换。
小技巧
你可以使用此代码片段来获取客户筛选条件并切换它们。
const customerFilters = this.env.searchModel.getSearchItems((searchItem) => searchItem.isFromAwesomeKanban ); for (const customerFilter of customerFilters) { if (customerFilter.isActive) { this.env.searchModel.toggleSearchItem(customerFilter.id); } }
将模板修改为给
CustomerList
的selectCustomer
属性赋予实际功能。
注解
你可以使用 Symbol 来确保自定义的 isFromAwesomeKanban
键不会与其他代码可能添加到对象中的键发生冲突。

5. 仅显示有激活订单的客户¶
在 res.partner
上有一个 opportunity_ids
字段。让我们允许用户筛选至少有一个机会的客户。
在
CustomerList
组件中添加一个类型为复选框的输入框,并在其旁边添加标签 “激活客户”。更改复选框的值应该会筛选客户列表。

6. 在客户列表中添加一个搜索栏¶
在客户列表上方添加一个输入框,允许用户输入字符串,并根据客户名称筛选显示的客户。
小技巧
你可以使用 @web/core/utils/search
文件中的 fuzzyLookup
函数来执行筛选。

另请参见
示例:使用 fuzzyLookup <https://github.com/odoo/odoo/blob/1f4e583ba20a01f4c44b0a4ada42c4d3bb074273/ addons/web/static/tests/core/utils/search_test.js#L17>`_
7. 重构代码以使用 t-model
¶
要解决前两个练习,你很可能在输入框上使用了事件监听器。让我们看看如何通过 t-model 指令以更声明式的方式实现。
确保你有一个响应式对象,用于表示筛选器是否激活(例如:
this.state = useState({ displayActiveCustomers: false, searchString: ''})
)。将代码修改为添加一个获取器
displayedCustomers
,该获取器返回当前激活的客户列表。将模板修改为使用
t-model
。
8. 对客户进行分页!¶
在
CustomerList
中添加一个 分页器,并且仅加载/渲染前 20 个客户。每当分页器发生变化时,客户列表应相应更新。
这实际上相当困难,尤其是在与前一练习中进行的筛选相结合时。需要考虑许多边界情况。
