
在Odoo的列表视图中,开发者经常需要根据特定业务逻辑动态地禁用某些行的复选框。例如,当一个产品的库存量为零时,可能需要禁用其对应的选择框,以防止用户对其进行操作。通常,这可以通过扩展ListRenderer并重写其_renderRow方法来实现,在行渲染时根据数据条件设置复选框的disabled属性。
然而,一个常见的问题是,当用户点击或修改列表视图中的任何一行时,之前被禁用的复选框会自动重新启用。这使得前端的禁用逻辑失效,需要刷新页面才能恢复。其根本原因在于Odoo的列表视图,特别是可编辑列表视图(ListEditableRenderer),在处理行编辑模式时,会通过其内部机制统一管理记录选择器的状态。具体来说,Odoo在进入编辑模式时可能会调用_disableRecordSelectors来禁用所有选择器,而在退出编辑模式或更新行后,会调用_enableRecordSelectors来重新启用它们。这些内部方法会覆盖我们在_renderRow中设置的disabled属性。
Odoo内部ListEditableRenderer中控制选择器的方法大致如下:
// Odoo 14.0/addons/web/static/src/js/views/list/list_editable_renderer.js
_disableRecordSelectors: function () {
this.$('.o_list_record_selector input').attr('disabled', 'disabled');
},
_enableRecordSelectors: function () {
this.$('.o_list_record_selector input').attr('disabled', false);
},这些方法会直接操作DOM,将所有.o_list_record_selector input元素的disabled属性设置为true或false,从而导致我们自定义的禁用逻辑被覆盖。
为了解决上述问题,我们需要创建一个自定义的列表渲染器,并不仅仅是重写_renderRow,更重要的是要介入Odoo对选择器启用/禁用过程的控制。核心思想是:在Odoo尝试重新启用所有选择器之后,我们再次根据业务逻辑判断并禁用那些应该保持禁用的复选框。
我们将创建一个新的JavaScript文件(例如:static/src/js/custom_list_renderer.js)来定义我们的自定义渲染器。
odoo.define('your_module_name.CustomListRenderer', function (require) {
"use strict";
var ListRenderer = require('web.ListRenderer');
var ListView = require('web.ListView');
var viewRegistry = require('web.view_registry');
// 定义需要保持禁用状态的类别
var CATEGORIES_TO_EXCLUDE = ['Maintenance', 'Installation', 'Transport', "Volume d'impression"];
var CustomListRenderer = ListRenderer.extend({
/**
* 扩展 _renderRow 方法,在初始渲染时禁用符合条件的复选框。
* 这是首次加载视图时应用禁用逻辑的地方。
*/
_renderRow: function (record) {
var tr = this._super.apply(this, arguments); // 调用父类的_renderRow方法获取原始行元素
// 根据库存和类别条件禁用复选框
var shouldBeDisabled = record.data.stock <= 0 && !CATEGORIES_TO_EXCLUDE.includes(record.data.small_category_name_field);
tr.find(".o_list_record_selector input[type='checkbox']").prop('disabled', shouldBeDisabled);
return tr;
},
/**
* 重写 _enableRecordSelectors 方法,确保在Odoo尝试启用所有选择器后,
* 仍然能够保持特定复选框的禁用状态。
*/
_enableRecordSelectors: function () {
this._super.apply(this, arguments); // 首先,调用父类方法,让Odoo启用所有选择器
var self = this;
// 遍历当前渲染的所有记录,重新应用禁用逻辑
this.records.forEach(function(record) {
// 查找当前记录对应的DOM行元素
var tr = self.$el.find('tr[data-id="' + record.id + '"]');
if (tr.length) {
var shouldBeDisabled = record.data.stock <= 0 && !CATEGORIES_TO_EXCLUDE.includes(record.data.small_category_name_field);
tr.find(".o_list_record_selector input[type='checkbox']").prop('disabled', shouldBeDisabled);
}
});
},
/**
* _disableRecordSelectors 方法通常可以保持不变,因为它只是全局禁用。
* 如果有特殊需求,也可以在此处添加逻辑。
*/
// _disableRecordSelectors: function () {
// this._super.apply(this, arguments);
// },
});
// 定义自定义ListView,并配置使用CustomListRenderer
var CustomListView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Renderer: CustomListRenderer,
}),
});
// 将自定义视图注册到视图注册表中,以便在XML中通过js_class引用
viewRegistry.add('custom_tree_renderer', CustomListView);
return {
CustomListRenderer: CustomListRenderer,
CustomListView: CustomListView,
};
});代码解析:
在你的Odoo模块的XML视图文件中,找到你想要应用此自定义逻辑的tree视图定义,并添加js_class属性,值为你在viewRegistry.add中注册的名称。
<record id="view_your_model_tree" model="ir.ui.view">
<field name="name">your.model.tree</field>
<field name="model">your.model</field>
<field name="arch" type="xml">
<tree js_class="custom_tree_renderer">
<!-- 你的字段定义 -->
<field name="name"/>
<field name="stock"/>
<field name="small_category_name_field"/>
<!-- ... 其他字段 ... -->
</tree>
</field>
</record>重要提示:
'assets': {
'web.assets_backend': [
'your_module_name/static/src/js/custom_list_renderer.js',
],
},通过扩展Odoo的ListRenderer并重写_renderRow和_enableRecordSelectors方法,我们可以有效地控制列表视图中复选框的禁用状态,使其在用户交互后依然保持稳定。这种方法深入理解了Odoo前端渲染机制,提供了一种健壮且可维护的解决方案,确保了自定义UI逻辑的持久性,从而显著提升了Odoo应用的可用性和用户体验。
以上就是Odoo v14中持久化列表视图复选框禁用状态的专业指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号