在 Odoo 18 表单视图中使用 JS 类的方法
一、模块结构创建
要为特定视图在 JavaScript 里注册一个类。后续在任意表单视图中添加相同类时,自定义视图就会被注入该表单。
具体要做的是:
- 把自定义视图创建出来当作模板。
- 将视图注册成一个组件。
- 把它和表单控制器连接起来。
之后,控制器一旦发现指定的类,就会执行对应的视图。
下面创建一个名为 test_model 的新模块,其结构如下:
test_model/
├── __manifest__.py
├── controllers/
├── models/
├── security/
├── static/
│ ├── src/
│ │ ├── js/
│ │ │ └── form_view_button.js
│ │ └── xml/
│ │ ├── form_view_button.xml
│ │ └── js_dialog.xml
└── views/
└── sale_order_views.xml
二、扩展表单视图并添加 js_class
首先在 views 目录下,对 sale.order 模型的表单视图进行扩展,给表单视图添加 js_class 属性以及类名。这里添加的 js_class 为 show_details,代码如下,保存为 sale_order_views.xml 文件:
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_sale_order_form_inherit" model="ir.ui.view">
<field name="name">sale.order.form.inherit</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//form" position="attributes">
<attribute name="js_class">show_details</attribute>
</xpath>
</field>
</record>
</odoo>
三、注册自定义视图组件
此时,表单控制器会去检查 JS 类 show_details 是否已在注册表中保存。所以,我们要在核心注册表中为自定义视图注册该类。
注册时,创建一个名为 showDetailsBtn 的新模板,为按钮使用 t-on-click 属性添加点击函数 actionDetailsForm。这里扩展 web 模块的表单视图,在表单视图顶部添加一个名为 “记录详情(Record Details)” 的新按钮。模板代码保存在 form_view_button.xml 文件中,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="test_model.showDetailsBtn" t-inherit="web.FormView">
<xpath expr="//t[@t-set-slot='layout-actions']" position="inside">
<button class="btn btn-primary" t-on-click="actionDetailsForm">
记录详情
</button>
</xpath>
</t>
</templates>
四、编写 JavaScript 控制器逻辑
接下来,要用 js 为表单定义点击函数。在 test_model/static/src/js/form_view_button.js 文件中,添加如下 JavaScript 代码:
/** @odoo-module **/
import { FormController } from "@web/views/form/form_controller";
import { formView } from '@web/views/form/form_view';
import { registry } from "@web/core/registry";
import { jsClassDialog } from "@test_model/js/js_dialog";
class jsClassRecordDetails extends FormController {
actionDetailsForm() {
this.env.services.dialog.add(jsClassDialog, {
resModel: this.props.resModel,
resDesc: "此弹窗用于演示通过 JS 类添加的自定义功能。"
});
}
}
jsClassRecordDetails.template = "test_model.showDetailsBtn";
export const recordDetailsView = {
...formView,
Controller: jsClassRecordDetails,
};
registry.category("views").add("show_details", recordDetailsView);
上面代码里的语句:
import { jsClassDialog } from "@test_model/js/js_dialog";
其作用是导入在我们模块的 static/src/xml/js_dialog.xml 文件中定义的自定义对话框。
然后在点击函数 actionDetailsForm 中调用对话框,并传入 resModel 和 resDesc 的值,当从销售订单的表单视图点击 “记录详情” 按钮时,这些值就会显示出来。
扩展出的新类是 jsClassRecordDetails,我们给它分配要加载的模板:
jsClassRecordDetails.template = "test_model.showDetailsBtn";
使用下面的语句在核心中注册 show_details 这个 JS 类:
registry.category("views").add("show_details", recordDetailsView);
五、创建对话框模板
下面来创建对话框模板,点击按钮时就会显示这个对话框。在 test_model/static/src/xml/js_dialog.xml 文件中添加如下代码:
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="test_model.infoDialog">
<Dialog size="'md'" title="'记录详情'" modalRef="modalRef">
<div class="p-4">
<h6>模型:</h6><span><t t-esc="props.resModel"/></span><br/>
<h6>描述:</h6><span><t t-esc="props.resDesc"/></span>
</div>
<t t-set-slot="footer">
<button class="btn btn-primary" t-att-class="props.confirmClass" t-on-click="clickClose" t-esc="props.confirmLabel"/>
</t>
</Dialog>
</t>
</templates>
这个对话框仅仅显示模型名称的详细信息和作为描述的自定义字符串行。
六、实现对话框逻辑
最后一步,添加 js 代码,使其在点击时加载对话框,代码如下:
/** @odoo-module **/
import { Component } from "@odoo/owl";
import { Dialog } from "@web/core/dialog/dialog";
import { _t } from "@web/core/l10n/translation";
export class jsClassDialog extends Component {
clickClose() {
this.props.close();
}
}
jsClassDialog.template = "test_model.infoDialog";
jsClassDialog.components = { Dialog };
jsClassDialog.title = _t("记录详情");
jsClassDialog.props = {
confirmLabel: { type: String, optional: true },
confirmClass: { type: String, optional: true },
resModel: { type: String, optional: true },
resDesc: { type: String, optional: true },
close: { type: Function, optional: true },
};
jsClassDialog.defaultProps = {
confirmLabel: _t("关闭"),
confirmClass: "btn-primary",
};
这段代码把对话框的模板指定为 test_model.infoDialog(其中 test_model 是我们的模块名称),还为对话框添加 props 值,用于设置标题、关闭按钮等内容。
最终,当我们在销售订单表单视图中点击 “记录详情” 按钮时,就会看到对话框打开。
总结
总的来说,Odoo 中的 JS 类功能能够依据开发人员的需求,灵活地自定义工作流程。对于 Odoo 开发人员而言,JS 类功能是非常有价值的资源,它带来了各种可能性,可以集成 JavaScript 函数,利用 JS 类功能增强 Odoo 表单视图。最终能充分发挥系统的潜力,为用户提供更具适应性和高效的系统。