Odoo 12表单中为单选按钮添加描述图标是否可行及实现方法
当然可以实现!在Odoo 12里,给单选按钮旁加图标、甚至多个带对应描述图标的单选框都完全没问题,我来给你一步步拆解具体操作:
一、核心思路
Odoo表单默认的单选按钮(也就是selection字段)没有直接内置图标支持,但咱们可以通过自定义QWeb模板或者扩展原生radio widget的方式来搞定——本质就是在渲染每个单选选项的时候,把图标元素插进去就行。
二、具体操作步骤
1. 先定义带图标标识的选择字段
首先在你的模型里定义一个selection字段,咱们可以把图标类名(比如Font Awesome的类)和选项文本放在一起,用分隔符分开,方便后续渲染。举个例子,做一个用户显示偏好的单选选项:
from odoo import models, fields class ResUsers(models.Model): _inherit = 'res.users' # 用|分隔选项文本和图标类 preference = fields.Selection([ ('light', '浅色模式|fa-sun-o'), ('dark', '深色模式|fa-moon-o'), ('system', '跟随系统|fa-desktop'), ], string='显示偏好', default='light')
2. 自定义QWeb模板渲染带图标的单选按钮
Odoo默认的radio按钮有对应的QWeb模板,咱们可以继承它并修改,在每个选项后面加上图标。在模块的views目录下创建一个XML文件(比如radio_icon_templates.xml):
<odoo> <!-- 继承原生radio模板,添加图标 --> <template id="radio_with_icon_template" inherit_id="web.radio" name="Radio Button with Icon"> <xpath expr="//td[hasclass('o_radio_item')]" position="inside"> <t t-set="label_parts" t-value="widget.field.selection_options[option_value][1].split('|')"/> <!-- 只有当存在图标类时才渲染 --> <t t-if="label_parts.length == 2"> <span t-attf-class="fa {{ label_parts[1] }} ml-2"/> <!-- 把选项文本单独显示,去掉图标类部分 --> <t t-set="widget.field.selection_options[option_value][1]" t-value="label_parts[0]"/> </t> </xpath> </template> </odoo>
这里用了Odoo默认集成的Font Awesome 4.x图标,所以直接用对应的类名就行,不用额外引入资源。
3. 在表单视图中应用自定义模板
接下来在你的表单视图里,给这个字段指定使用咱们的自定义模板。比如继承用户表单视图,添加这个字段:
<odoo> <record id="res_users_form_inherit" model="ir.ui.view"> <field name="name">res.users.form.inherit.icon.radio</field> <field name="model">res.users</field> <field name="inherit_id" ref="base.view_users_form"/> <field name="arch" type="xml"> <!-- 把字段加在邮箱字段后面 --> <xpath expr="//field[@name='email']" position="after"> <field name="preference" widget="radio" options="{'template': 'your_module_name.radio_with_icon_template'}"/> </xpath> </field> </record> </odoo>
记得把your_module_name换成你自己的模块名称哦。
4. 更灵活的方式:自定义Widget
如果你需要更复杂的逻辑(比如动态切换图标、自定义样式),可以写一个自定义的radio widget。在模块的static/src/js目录下创建radio_with_icon.js:
odoo.define('your_module_name.radio_with_icon_widget', function(require) { "use strict"; var core = require('web.core'); var Radio = require('web.Radio'); // 继承原生Radio widget,重写渲染选项的方法 var RadioWithIcon = Radio.extend({ _renderItem: function(id, label, value) { // 先调用原生方法渲染基础的单选按钮 var $item = this._super(id, label, value); // 拆分选项文本和图标类 var labelParts = label.split('|'); if (labelParts.length === 2) { // 在标签后面添加图标 $item.find('.o_radio_label').after('<span class="fa ' + labelParts[1] + ' ml-2"></span>'); // 更新标签文本,只显示选项名称 $item.find('.o_radio_label').text(labelParts[0]); } return $item; }, }); // 把自定义widget注册到表单组件里 core.form_widget_registry.add('radio_with_icon', RadioWithIcon); return RadioWithIcon; });
然后在XML里加载这个JS文件,让Odoo能识别它:
<odoo> <template id="assets_backend_radio_icon" inherit_id="web.assets_backend"> <xpath expr="." position="inside"> <script type="text/javascript" src="/your_module_name/static/src/js/radio_with_icon.js"/> </xpath> </template> </odoo>
之后在表单视图里直接用这个自定义widget就行:
<field name="preference" widget="radio_with_icon"/>
三、几个注意点
- 记得在模块的
__manifest__.py里添加'depends': ['web'],确保依赖web模块 - Odoo 12用的是Font Awesome 4.x,所以图标类要对应这个版本(比如
fa-sun-o,不是新版的fa-sun) - 如果要用自己的自定义图标,把图标路径存在selection里,然后把模板里的
<span>换成<img>标签就行
这样就能实现每个单选按钮旁都带对应描述图标的需求啦!
内容的提问来源于stack exchange,提问作者Adham Baquroun

