
本文详解如何在 odoo 16 中为 one2many 行内的进度条(progressbar)创建自定义字段组件,并基于计算字段或配置选项动态设置背景色,解决 missing widget 错误及模板继承问题。
本文详解如何在 odoo 16 中为 one2many 行内的进度条(progressbar)创建自定义字段组件,并基于计算字段或配置选项动态设置背景色,解决 missing widget 错误及模板继承问题。
在 Odoo 16 中,web.basic_fields.FieldProgressBar 已被重构为 OWL 组件(位于 @web/views/fields/progress_bar/progress_bar_field.js),因此旧版 odoo.define + field_registry 的写法不再适用——这正是你遇到 Missing widget: CustomProgressBar 报错的根本原因。正确方式是使用现代 OWL 模块注册机制,并通过模板继承与属性注入实现动态样式。
✅ 正确注册自定义进度条字段
首先,在你的模块 JS 文件(如 static/src/js/custom_progressbar_field.js)中,按标准 OWL 方式继承并注册:
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { ProgressBarField } from "@web/views/fields/progress_bar/progress_bar_field";
export class CustomProgressBarField extends ProgressBarField {
// 可在此添加生命周期钩子(如 willUpdate、mounted)或自定义逻辑
}
// 注册为新字段类型,名称需与 XML 中的 widget="custom_progressbar" 严格一致
registry.category("fields").add("custom_progressbar", CustomProgressBarField);
⚠️ 注意:
- 必须使用 /** @odoo-module **/ 注释声明模块;
- registry.category("fields") 是 Odoo 16+ 的标准注册入口;
- 确保该 JS 文件已加入 __manifest__.py 的 assets → "web.assets_backend" 列表中。
? 动态着色:两种推荐方案
方案一:基于记录字段值(如 color_level 计算字段)
适用于颜色逻辑简单、直接映射到 Bootstrap 类名(如 bg-success / bg-warning)的场景。
1. 定义模板(static/src/xml/custom_progressbar_template.xml):
<?xml version="1.0" encoding="UTF-8"?><templates xml:space="preserve"><t t-name="web.CustomProgressBarField" t-inherit="web.ProgressBarField" t-inherit-mode="primary" owl="1"><xpath expr="//div[hasclass('o_progress')]/div" position="attributes"><attribute name="t-attf-class">
o_progress_bar_value
t-if="props.record.data.color_level === 1" bg-success
t-elif="props.record.data.color_level === 2" bg-warning
t-else bg-danger
h-100
</attribute></xpath></t></templates>
2. 在 Python 模型中定义计算字段(示例):
from odoo import models, fields, api
class YourLineModel(models.TransientModel):
_name = 'your.line.model'
progress = fields.Integer(string='Progress (%)', default=0)
color_level = fields.Integer(compute='_compute_color_level', store=True)
@api.depends('progress')
def _compute_color_level(self):
for rec in self:
if rec.progress >= 80:
rec.color_level = 1 # green
elif rec.progress >= 50:
rec.color_level = 2 # yellow
else:
rec.color_level = 3 # red
3. XML 视图中使用:
<field name="line_ids"><tree editable="bottom"><field name="progress" widget="custom_progressbar"></field><!-- color_level 字段需存在但可 invisible --><field name="color_level" invisible="1"></field></tree></field>
方案二:基于字段选项传入颜色值(更灵活)
当需要精确控制 RGB/HEX 色值(如 #ff6b35)时,推荐此方式。
1. 增强字段属性支持(JS):
// static/src/js/custom_progressbar_field.js
export class CustomProgressBarField extends ProgressBarField {}
CustomProgressBarField.template = "chn_event_availability_manager.custom_progressbar_template";
// 扩展 props 支持 color_field 选项
CustomProgressBarField.props = {
...ProgressBarField.props,
colorField: { type: String, optional: true },
};
CustomProgressBarField.extractProps = ({ attrs }) => {
const parentProps = ProgressBarField.extractProps({ attrs });
return {
...parentProps,
colorField: attrs.options?.color_field || 'default_color',
};
};
registry.category("fields").add("custom_progressbar", CustomProgressBarField);
2. 自定义模板(支持内联 style):
<t t-name="chn_event_availability_manager.custom_progressbar_template" t-inherit="web.ProgressBarField" t-inherit-mode="primary" owl="1"><xpath expr="//div[hasclass('o_progress')]/div" position="attributes"><attribute name="t-att-style">
'width: min(' + 100 * state.currentValue / state.maxValue + '%, 100%)' +
';background-color: ' + (props.record.data[props.colorField] || '#007bff') + ' !important'
</attribute></xpath></t>
3. 视图中传入选项:
<field name="progress" widget="custom_progressbar" options="{'color_field': 'hex_color'}"></field><field name="hex_color" invisible="1"></field><!-- 如字段值为 '#28a745' -->
? 关键注意事项
- 模板命名必须唯一且全局可见:t-name 值不能与现有模板冲突,建议带模块前缀;
-
OWL XPath 表达式需精准匹配://div[hasclass('o_progress')]/div 是 Odoo 16 进度条内部 下的填充条容器;
- CSS 优先级问题:使用 !important 确保覆盖默认 background-color;
- One2Many 上下文安全:props.record.data 在 transient model 中完全可用,无需额外处理;
- 调试技巧:在浏览器控制台执行 odoo.__DEBUG__.services['web.field_registry'] 可验证字段是否注册成功。
通过以上结构化实现,你不仅能彻底解决 Missing widget 异常,还能灵活扩展颜色逻辑——无论是语义化类名映射,还是动态 HEX 值渲染,均能稳定运行于 Odoo 16 的 OWL 架构之上。











