Odoo11自定义Javascript Widget动作失效:ClientWidget不是函数?求指导
解决Odoo11自定义JS组件报错「ClientWidget is not a function」的问题
嘿,我来帮你搞定这个Odoo11的前端组件问题!从你描述的报错和代码片段来看,大概率是组件引用或者模板调用出了问题,我给你梳理一下排查思路和可运行的完整示例,你可以对照着调整。
一、先搞懂报错的根源
「ClientWidget is not a function」这个错误,基本上逃不开两种情况:
- 模板里写错了组件名:Odoo11的前端基础组件是
web.Widget,根本没有ClientWidget这个东西,如果你的XML模板(就是对应ProductsWidget的那个模板)里误用了这个不存在的组件名,肯定会报错。 - JS模块和组件的命名/注册混乱:你代码里定义的模块是
tour_demo.tour,但你的模块叫petstore,组件是ProductsWidget,这种命名不匹配很容易导致Odoo找不到你的组件。
二、给你一套可直接复用的完整示例
我按照你的petstore模块结构,写了一套能正常运行的自定义Widget代码,你可以直接参考修改:
1. 修正后的JS代码(petstore/static/src/js/petstore.js)
odoo.define('petstore.products_widget', function(require) { "use strict"; // 引入Odoo11需要的基础模块 var Widget = require('web.Widget'); var core = require('web.core'); var Model = require('web.Model'); // Odoo11里用这个做数据查询 // 定义你的自定义Widget var ProductsWidget = Widget.extend({ template: 'ProductsWidget', // 和XML模板的t-name对应 init: function(parent, options) { this._super(parent, options); this.products = []; // 先初始化数据容器 }, start: function() { // 组件渲染完成后,加载产品数据 var self = this; new Model('product.product').query(['name', 'list_price']) .limit(5) // 只取前5个产品 .all().then(function(products) { self.products = products; self.renderElement(); // 更新渲染模板 }); return this._super(); }, }); // 把组件注册到Odoo的动作注册表,这样才能被调用 core.action_registry.add('petstore.products_widget', ProductsWidget); return ProductsWidget; });
2. 对应的XML模板(petstore/static/src/xml/petstore_templates.xml)
<?xml version="1.0" encoding="UTF-8"?> <templates id="template" xml:space="preserve"> <!-- 模板名必须和JS里的template属性完全一致 --> <t t-name="ProductsWidget"> <div class="products-widget"> <h3>热门商品列表</h3> <ul class="product-list"> <!-- 循环渲染产品数据 --> <t t-foreach="widget.products" t-as="product"> <li> <span t-esc="product.name"/> - <span class="price" t-esc="product.list_price"/> 元 </li> </t> </ul> </div> </t> </templates>
3. 配置模块资产(petstore/views/assets.xml)
必须把你的JS和模板加到Odoo的后端资产里,不然前端根本加载不到:
<?xml version="1.0" encoding="UTF-8"?> <odoo> <data> <!-- 把JS和样式加到后端资产 --> <template id="assets_backend" name="petstore backend assets" inherit_id="web.assets_backend"> <xpath expr="." position="inside"> <script type="text/javascript" src="/petstore/static/src/js/petstore.js"></script> <!-- 如果有自定义样式,可以在这里引入 --> <!-- <link rel="stylesheet" href="/petstore/static/src/css/petstore.css"/> --> </xpath> </template> <!-- 加载XML模板 --> <template id="petstore_templates" inherit_id="web.layout"> <xpath expr="//t[@id='assets']" position="inside"> <xml id="petstore_templates_xml" name="petstore templates" src="/petstore/static/src/xml/petstore_templates.xml"/> </xpath> </template> </data> </odoo>
4. 如何调用这个组件
给你加个菜单动作,这样就能在后台直接看到效果了:
<?xml version="1.0" encoding="UTF-8"?> <odoo> <!-- 创建客户端动作 --> <record id="action_products_widget" model="ir.actions.client"> <field name="name">商品列表组件</field> <field name="tag">petstore.products_widget</field> <!-- 和JS里注册的tag对应 --> </record> <!-- 把动作加到菜单里 --> <menuitem id="menu_products_widget" name="商品组件演示" parent="base.menu_reporting" action="action_products_widget"/> </odoo>
三、几个必须注意的坑
- 命名要统一:JS模块名、组件注册名、模板名一定要对应上,你之前写的
tour_demo.tour和模块名petstore不搭,这种混乱很容易让Odoo找不到你的代码。 - 别用错Odoo11的API:Odoo11用
web.Model查数据,后续版本才改成web.DataManager,别拿新版本的代码往11里套。 - 调试技巧:打开浏览器F12,在Sources里找到你的JS文件,打个断点一步步看,组件初始化、数据加载、模板渲染哪步出问题一目了然。
如果按上面的步骤改完还是有问题,把你的完整模板代码和报错的完整堆栈信息贴出来,我再帮你细查~
内容的提问来源于stack exchange,提问作者user_123
相关产品推荐
相关产品推荐

