Odoo 15如何用JavaScript动态将编辑字段设为只读且不破坏视图?
Odoo 15 动态切换字段编辑/只读模式的可行方案
问题根源
你直接重写_render强制返回只读渲染的做法,会跳过编辑模式下的DOM初始化逻辑——比如输入框创建、事件绑定这些步骤。当字段原本处于编辑模式时,视图依赖的编辑态DOM根本没生成,自然就会导致界面损坏。
实现方案
1. 继承目标字段组件(以FieldChar为例)
通过继承原生的web.basic_fields.FieldChar,添加动态切换逻辑,同时保留原有的渲染分支,确保两种模式的DOM都能正常初始化:
odoo.define('your_module.custom_field_char', function (require) { "use strict"; const FieldChar = require('web.basic_fields').FieldChar; const fieldRegistry = require('web.field_registry'); const CustomFieldChar = FieldChar.extend({ /** * 动态切换字段只读状态 * @param {boolean} isReadonly - 是否设为只读 */ toggleReadonly: function (isReadonly) { this.nodeOptions.readonly = isReadonly; // 触发组件重新渲染 this.render(); }, // 保留原生渲染逻辑,根据当前readonly状态自动选渲染模式 _render: function () { if (this.nodeOptions.readonly) { return this._renderReadonly(); } else { return this._renderEdit(); } }, }); // 注册自定义字段,替换原生FieldChar(也可以注册成新类型,比如custom_char) fieldRegistry.add('char', CustomFieldChar); return CustomFieldChar; });
2. 在视图中触发切换逻辑
比如在按钮点击事件里,获取字段组件实例并调用切换方法:
// 示例:绑定按钮点击事件 this.$('.toggle-readonly-btn').on('click', () => { // 获取目标字段的组件实例(根据实际视图结构调整字段名) const fieldComp = this.fields['your_target_field']; if (fieldComp) { // 切换状态:取反当前只读状态 const currentState = fieldComp.nodeOptions.readonly; fieldComp.toggleReadonly(!currentState); } });
3. 处理视图模式切换的同步
如果需要在视图的浏览/编辑模式切换时,保持自定义的只读状态,可以重写_setMode方法:
_setMode: function (mode) { this._super.apply(this, arguments); // 示例:切到编辑模式时,强制字段保持只读 if (mode === 'edit') { this.nodeOptions.readonly = true; this.render(); } }
注意事项
- 别直接覆盖原生字段的核心方法,避免破坏Odoo原生逻辑
- 如果只需要给特定字段生效,别全局替换FieldChar,注册成新字段类型(比如
custom_char),在视图XML里指定该类型即可 - 切换状态后一定要调用
render()触发重渲染,别手动修改DOM
内容的提问来源于stack exchange,提问作者jacobbrds
相关产品推荐
相关产品推荐

