Javascript 参考手册

本文介绍了Odoo的Javascript框架。这个框架在代码行数方面并不是一个大型应用程序,但它非常通用,因为它基本上是一个将声明性接口描述转换为能够与数据库中的每个模型和记录进行交互的实时应用程序的机器。甚至可以使用Web客户端修改Web客户端的界面。

概述

Javascript框架旨在处理三种主要用例:

  • the web client: 这是私有的网络应用程序,可以查看和编辑业务数据。这是一个单页应用程序(页面从不重新加载,只有在需要时才从服务器获取新数据)

  • the website: 这是 Odoo 的公开部分。它允许未识别的用户以客户身份浏览内容、购物或执行许多操作。这是一个典型的网站:包含各种路由和控制器,以及一些使其运行的 javascript。

  • 销售点:这是销售点的界面。它是一个专门的单页应用程序。

一些 JavaScript 代码在这三种使用场景中是通用的,并且被打包在一起(参见下面的资产部分)。本文档将主要关注 Web 客户端的架构。

Web客户端

单页应用程序

Web 客户端是一个单页应用程序:每次用户执行操作时,它不会从服务器请求整个页面,而是仅加载更新用户界面(UI)所需的内容。在此过程中,它还会负责更新 URL 中的信息,因此在大多数情况下,刷新页面或关闭浏览器后再次打开,显示的仍然是相同的内容。

Web客户端JS代码概述

这里,我们简要概述了 web 插件中的网页客户端代码。路径将相对于 web/static/src 进行描述。以下描述特意不全面;目的是让读者对架构有一个概览。

  • module_loader.js:这是定义 Odoo JavaScript 模块系统的文件。它需要在加载任何其他 JS 模块之前被加载。

  • core/: 该文件夹包含构成 JavaScript 框架最底层的代码,这些代码可以在 Web 客户端以及网站、门户和销售点应用程序中使用。

  • weblient/: 该文件夹包含特定于 Web 客户端的文件,这些文件不能用于网站或销售点,例如操作管理器和操作服务。

  • webclient/webclient.js: 这是 webclient 组件本身。它主要是 action 容器和导航栏的封装器,并执行一些在启动应用程序时所需的操作,例如加载 URL 的状态。

  • webclient/actions/: 该文件夹包含负责显示和切换操作的代码。

  • views/: 此文件夹包含视图基础设施的代码,以及大多数视图(某些类型的视图由其他插件添加)。

  • views/fields/: 包含各种字段组件的定义,以及一些被多个字段使用的工具。

  • search/ 所有这些文件定义了搜索视图(从Web客户端的角度来看,它不是一个视图,仅从服务器的角度来看)

如果文件未加载/更新该怎么办

有很多不同的原因可能导致文件无法正确加载。以下是您可以尝试解决问题的一些方法:

  • 确保您已保存文件;忘记保存这种事,即使是最优秀的人也会发生。

  • 查看控制台(在开发者工具中,通常通过 F12 打开)并检查错误。

  • 尝试在文件开头添加一个 console.log() ,以便查看文件是否已加载。如果未加载,可能未包含在正确的资产包中,或者资产包可能未更新。

  • 根据您的设置,服务器在文件修改后可能不会重新生成资产包;有几种方法可以解决此问题:

    • 重启服务器将强制它在下次请求时检查资源包是否为最新版本

    • 在调试模式下,调试菜单中有一个选项(导航栏中的 按钮)可以强制服务器在不重启的情况下动态重新生成资源包。

    • 使用 --dev=xml 选项启动服务器将强制服务器在每次请求时检查资源包是否为最新。我们建议您在积极开发时使用此选项,但不要在生产环境中使用。

  • 更改代码后,请确保刷新页面。Odoo 目前没有任何热模块重载机制。

加载 JavaScript 代码

大型应用程序通常被拆分为较小的文件,这些文件需要连接在一起。某些文件可能需要使用另一个文件中定义的代码。有两种方式可以在文件之间共享代码:

  • 使用全局作用域(即 window 对象)来读取/写入某些对象或函数的引用,

  • 使用一个模块系统,该系统将为每个模块提供导出或导入值的方式,并确保它们以正确的顺序加载。

虽然在全局范围内工作是可能的,但这会带来许多问题:

  • 很难确保实现细节不被暴露:全局作用域中的函数声明对所有其他代码都是可访问的。

  • 有一个单一的命名空间,这为命名冲突带来了很大的潜在风险。

  • 依赖关系是隐式的:如果一段代码依赖于另一段代码,它们的加载顺序很重要,但难以保证。

使用模块系统有助于解决这些问题:因为模块指定了它们的依赖关系,模块系统可以按正确的顺序加载它们,或者在依赖缺失或循环时发出错误。模块还形成了自己的命名空间,并可以选择导出什么,从而防止实现细节的暴露和命名冲突。

虽然我们可以直接使用 ECMAScript (ES) 模块,但这种方法存在一些缺点:每个 ES 模块都需要进行网络往返,当你有数百个文件时,这会变得非常缓慢,而且 Odoo 中的许多文件需要存在,尽管它们没有被任何东西导入,因为它们只是添加了框架将使用的代码,而不是相反。

正因如此,Odoo 拥有一个资源包系统。在这些包中,JavaScript 文件是带有顶部特殊注解的 ES 模块。这些模块将被捆绑在一起并转译,以便我们的模块加载器能够使用。虽然你可以编写不使用此模块系统的代码,但通常不建议这样做。

(参见 本地 JavaScript 模块)

Patching classes

尽管我们尽力提供无需修改的扩展点,但有时仍需要 就地 修改现有类的行为。目标是拥有一种机制,可以更改类及其所有未来/现有实例。这是通过使用 patch 工具函数来实现的:

/** @odoo-module */
import { Hamster } from "@web/core/hamster"
import { patch } from "@web/core/utils/patch";

patch(Hamster.prototype, {
    sleep() {
        super.sleep(...arguments);
        console.log("zzzz");
    },
});

在修补方法时,你需要修补类的原型,但如果你想修补类的静态属性,你需要直接修补类本身。

Patching 是一项危险操作,应谨慎进行,因为它将修改类的所有实例,即使它们已经创建。为了避免奇怪的问题,补丁应尽快应用,位于模块的顶层。如果在运行时对类进行修补,且该类已经实例化,可能会导致极其难以调试的问题。

注册表

在 Odoo 生态系统中,一个常见的需求是从外部扩展/更改基础系统的行为(通过安装应用程序,即不同的模块)。例如,可能需要在某些视图中添加一个新的字段小部件。在这种情况下,以及许多其他情况下,通常的流程是创建所需的组件,然后将其添加到注册表中(注册步骤),以使 Web 客户端的其余部分知道其存在。

系统中有几个可用的注册表。框架使用的注册表是主注册表上的类别,可以从 @web/core/registry 导入。

field registry

字段注册表包含所有已知的字段小部件。每当视图(通常是表单或列表/看板)需要字段小部件时,它会在这里查找。典型的用例如下:

import { registry } from "@web/core/registry";
class PadField extends Component { ... }

registry.category("fields").add("pad", {
  component: PadField,
  supportedTypes: ["char"],
  // ...
});
查看注册表

该注册表包含 web 客户端已知的所有 JS 视图。

动作注册表

我们在此注册表中跟踪所有客户端操作。这是操作管理器在需要创建客户端操作时查找的地方。客户端操作可以是一个函数——当操作被调用时,该函数将被调用,并且如果需要,返回值将作为后续操作执行——或者是一个在执行该操作时将显示的 Owl 组件。

服务

在 webclient 中,有一些问题无法由单个组件处理,因为这些问题具有横向性,涉及多个组件,或者需要在应用程序存活期间维护某些状态。

Services 是这些问题的解决方案:它们在应用程序启动时创建,通过钩子 useService 对组件可用,并在应用程序的整个生命周期内保持活动状态。

例如,我们有 orm 服务,其职责是允许与服务器上的业务对象进行交互。

以下是关于 orm 服务如何实现的简化示例:

import { registry } from "@web/core/registry";
export const OrmService = {
    start() {
        return {
            read(...) { ... },
            write(...) { ... },
            unlink(...) { ... },
            ...
        }
    },
};
registry.category("services").add("orm", OrmService);

Using services

服务在环境中可用,但通常应通过 useService 钩子使用,这样可以防止在组件销毁后调用服务上的方法,并防止在方法调用期间组件被销毁后进一步执行代码。

class SomeComponent extends Component {
    setup() {
        this.orm = useService("orm");
    }
    // ...
    getActivityModelViewID(model) {
        return this.orm.call(model, "get_activity_view_id", this.params);
    }
}

与服务器通信

在 Odoo 中工作时,通常有两种使用场景:一种可能是需要在 (python) 模型上调用方法(这会通过控制器 /web/dataset/call_kw),另一种可能是需要直接调用控制器(在某些路由上可用)。

  • 在 Python 模型上调用方法是通过 orm 服务完成的:

    return this.orm.call("some.model", "some_method", [some, args]);
    
  • 直接调用控制器是通过 rpc 服务完成的:

    return this.rpc("/some/route/", {
        some: param,
    });
    

注解

rpc 服务并不真正执行通常理解的远程过程调用(RPC),但由于历史原因,在 Odoo 中我们通常将 JavaScript 中执行的任何网络请求称为 RPC。正如前一段所强调的,如果你想在模型上调用一个方法,你应该使用 orm 服务。

通知

Odoo 框架有一种标准的方式向用户传达各种信息:通知,这些通知显示在用户界面的右上角。通知的类型遵循 bootstrap toasts:

  • info: 用于显示一些信息反馈,通常是在某个不会失败的操作后显示。

  • success:用户执行了一个有时可能会失败但未失败的操作。

  • warning:用户执行了一个只能部分完成的操作。如果某些事情出了问题,但不是由用户直接引起的,或者不是特别可操作的,这也很有用。

  • success: 用户尝试执行某个操作,但未能完成。

通知也可以用于在不打扰用户工作流程的情况下向用户提问:例如,通过 VOIP 接到的电话:可以显示一个粘性通知,其中包含两个按钮,用于 接听拒绝

显示通知

在 Odoo 中有两种显示通知的方式:

  • notification 服务允许组件通过调用 add 方法从 JS 代码显示通知。

  • display_notification 客户端操作允许从 Python 触发通知的显示(例如,在用户点击类型为 object 的按钮时调用的方法中)。此客户端操作使用通知服务。

通知有一些 选项

  • title: 字符串,可选。这将显示在顶部作为标题。

  • message: 字符串,可选。通知的内容。可以是一个标记对象,用于显示格式化文本。

  • sticky: 布尔值,可选(默认为 false)。如果为 true,则通知将一直保持显示,直到用户关闭它。否则,通知将在短时间后自动关闭。

  • type: 字符串,可选(默认为 “warning”)。决定通知的样式。可能的值有:”info”、”success”、”warning”、”danger”

  • className: string, 可选。这是一个 CSS 类名,将自动添加到通知中。尽管不鼓励使用,但这可能对样式设计有用。

以下是一些如何在 JS 中显示通知的示例:

// note that we call _t on the text to make sure it is properly translated.
this.notification.add({
    title: _t("Success"),
    message: _t("Your signature request has been sent.")
});
this.notification.add({
    title: _t("Error"),
    message: _t("Filter name is required."),
    type: "danger",
});

在 Python 中:

# note that we call _(string) on the text to make sure it is properly translated.
def show_notification(self):
    return {
        'type': 'ir.actions.client',
        'tag': 'display_notification',
        'params': {
            'title': _('Success'),
            'message': _('Your signature request has been sent.'),
            'sticky': False,
        }
    }

系统托盘

Systray 是界面中导航栏的右侧部分,网页客户端在此显示一些小部件,例如消息菜单。

当导航栏创建系统托盘时,它将查找所有已注册的系统托盘项并显示它们。

目前没有针对 systray 项目的特定 API。它们是 Owl 组件,可以像其他组件一样与其环境进行通信,例如通过与服务交互。

添加新的系统托盘项目

可以通过将项目添加到 “systray” 注册表来将它们添加到系统托盘中:

import { registry } from "@web/core/registry"
class MySystrayComponent extends Component {
    ...
}
registry.category("systray").add("MySystrayComponent", MySystrayComponent, { sequence: 1 });

项目在系统托盘中的顺序根据它们在系统托盘注册表中的顺序排列。

翻译管理

部分翻译在服务器端完成(基本上所有由服务器渲染或处理的文本字符串),但静态文件中也有一些字符串需要翻译。目前的工作方式如下:

  • 每个可翻译的字符串都用特殊函数 _t 标记

  • 这些字符串用于服务器生成正确的 PO 文件

  • 每当网络客户端被加载时,它会调用路由 /web/webclient/translations,该路由返回所有可翻译术语的列表

  • 在运行时,每当函数 _t 被调用时,它都会在此列表中查找以找到翻译,并返回它,如果未找到,则返回原始字符串。

请注意,有关翻译的更详细解释,从服务器的角度来看,请参阅文档 翻译模块

import { _t } from "@web/core/l10n/translation";

class SomeComponent extends Component {
    static exampleString = _t("this should be translated");
    ...
    someMethod() {
        const str = _t("some text");
    }
}

注意,使用翻译功能时需要小心:作为参数传递的字符串不能是动态的,因为它是从代码中静态提取以生成 PO 文件的,并作为要翻译术语的标识符。如果你需要在字符串中注入一些动态内容,_t 支持占位符:

import { _t } from "@web/core/l10n/translation";
const str = _t("Hello %s, you have %s unread messages.", user.name, unreadCount);

注意字符串本身是固定的。这使得翻译函数能够在用于插值 之前 检索到翻译后的字符串。

会话

Web客户端需要从Python获取一些信息才能正常运行。为了避免在JavaScript中发起网络请求而导致的额外服务器往返,这些信息被直接序列化在页面中,并且可以通过 @web/session 模块在JS中访问。

向会话添加信息

当加载 /web 路由时,服务器会将此信息注入到一个脚本标签中。该信息通过调用模型 ir.httpsession_info 方法获得。你可以重写此方法以向返回的字典中添加信息。

from odoo import models
from odoo.http import request

class IrHttp(models.AbstractModel):
    _inherit = 'ir.http'

    def session_info(self):
        result = super(IrHttp, self).session_info()
        result['some_key'] = get_some_value_from_db()
        return result

现在,可以通过在会话中读取它来在 JavaScript 中获取该值:

import { session } from "@web/session"
const myValue = session.some_key;
...

请注意,此机制旨在减少 Web 客户端准备就绪所需的通信量。它仅适用于计算成本较低的数据(缓慢的 session_info 调用会延迟所有人的 Web 客户端加载),以及初始化过程早期所需的数据。

查看

单词 “view” 有多种含义。本节讨论的是视图的 JavaScript 代码设计,而不是 arch 的结构或其他内容。

虽然视图只是 owl 组件,但内置视图通常具有相同的结构:一个名为 “SomethingController” 的组件,它是视图的根组件。该组件创建某个 “model” 的实例(负责管理数据的对象),并有一个名为 “renderer” 的子组件,用于处理显示逻辑。

字段

网页客户端体验的重要部分是编辑和创建数据。大部分工作都是通过字段小部件完成的,它们了解字段类型以及特定细节,如何显示和编辑值。

装饰

与列表视图类似,字段小部件对装饰有简单的支持。装饰的目的是根据记录的当前状态,提供一种简单的方式来指定文本颜色。例如:

<field name="state" decoration-danger="amount &lt; 10000"/>

有效的装饰名称为:

  • decoration-bf

  • decoration-it

  • decoration-danger

  • decoration-info

  • decoration-muted

  • decoration-primary

  • decoration-success

  • decoration-warning

每个修饰符 decoration-X 将被映射到一个 css 类 text-X,这是一个标准的 bootstrap css 类(除了 text-ittext-bf,它们由 odoo 处理并分别对应斜体和粗体)。请注意,修饰符属性的值应该是一个有效的 Python 表达式,它将在记录作为评估上下文时进行评估。

非关系型字段

我们在此记录所有默认提供的非关系字段,没有特定的顺序。

整数 (integer)

这是 integer 类型字段的默认字段类型。

  • 支持的字段类型:integer

选项:

  • type: 设置输入类型(默认为 "text",可以设置为 "number"

    在编辑模式下,该字段被渲染为一个输入框,其 HTML 属性类型设置为 `”number”`(因此用户可以受益于原生支持,尤其是在移动设备上)。在这种情况下,默认的格式化被禁用以避免不兼容性。

    <field name="int_value" options="{'type': 'number'}" />
    
  • step:设置当用户点击按钮时数值的增减步长(仅适用于类型为 number 的输入框,默认为 1

    <field name="int_value" options="{'type': 'number', 'step': 100}" />
    
  • format: 数字是否应该被格式化。(默认为 true

    默认情况下,数字根据区域设置参数进行格式化。此选项将阻止字段的值被格式化。

    <field name="int_value" options='{"format": false}' />
    
Float (float)

这是 float 类型字段的默认字段类型。

  • 支持的字段类型:float

属性:

  • digits: displayed precision

    <field name="factor" digits="[42,5]" />
    

选项:

  • type: 设置输入类型(默认为 "text",可以设置为 "number"

    在编辑模式下,该字段被渲染为一个输入框,其 HTML 属性类型设置为 `”number”`(因此用户可以受益于原生支持,尤其是在移动设备上)。在这种情况下,默认的格式化被禁用以避免不兼容性。

    <field name="int_value" options="{'type': 'number'}" />
    
  • step:设置当用户点击按钮时数值的增减步长(仅适用于类型为 number 的输入框,默认为 1

    <field name="int_value" options="{'type': 'number', 'step': 0.1}" />
    
  • format: 数字是否应该被格式化。(默认为 true

    默认情况下,数字根据区域设置参数进行格式化。此选项将阻止字段的值被格式化。

    <field name="int_value" options="{'format': false}" />
    
时间 (float_time)

此小部件的目标是正确显示表示时间间隔(以小时为单位)的浮点值。因此,例如,0.5 应格式化为 0:30,或 4.75 对应 4:45

  • 支持的字段类型:float

Float Factor (float_factor)

此小部件旨在正确显示使用其选项中给定的因子转换后的浮点值。因此,例如,数据库中保存的值为 0.5,因子为 3,小部件的值应格式化为 1.5

  • 支持的字段类型:float

Float Toggle (float_toggle)

该小部件的目标是用一个包含一系列可能值(在选项中给出)的按钮替换输入字段。每次点击允许用户在范围内循环。这里的目的是将字段值限制为预定义的选择。此外,该小部件支持与 float_factor 小部件相同的因子转换(范围值应为转换的结果)。

  • 支持的字段类型:float

<field name="days_to_close" widget="float_toggle" options="{'factor': 2, 'range': [0, 4, 8]}" />
布尔值 (boolean)

这是 boolean 类型字段的默认字段类型。

  • 支持的字段类型:boolean

Char (char)

这是 char 类型字段的默认字段类型。

  • 支持的字段类型:char

日期 (date)

这是 date 类型字段的默认字段类型。它由一个文本框和一个日期选择器组成。

  • 支持的字段类型: date

选项:

  • min_date / max_date:设置可接受值的日期限制。默认情况下,最早可接受的日期为 1000-01-01,最晚为 9999-12-31。可接受的值为 SQL 格式的日期 (yyyy-MM-dd HH:mm:ss) 或 "today"

    <field name="datefield" options="{'min_date': 'today', 'max_date': '2023-12-31'}" />
    
  • warn_future: 如果值在未来(基于今天),则显示警告。

    <field name="datefield" options="{'warn_future': true}" />
    
Date & Time (datetime)

这是 datetime 类型字段的默认字段类型。值始终位于客户端的时区。

  • 支持的字段类型:datetime

选项:

  • 请参见 日期字段 选项

  • rounding: 用于在时间选择器中生成可用分钟的增量。这不会影响实际值,只会影响选择下拉菜单中的可用选项数量(默认值:5)。

    <field name="datetimefield" options="{'rounding': 10}" />
    
  • show_seconds:当设置为 false 时,它会隐藏 datetime 字段中的秒数。该字段仍然会接受 datetime 值,但在 UI 中秒数将被隐藏(默认值:true)。

    <field name="datetimefield" widget="datetime" options="{'show_seconds': false}" />
    
  • show_time:当设置为 false 时,它会隐藏日期时间字段中的时间部分。该字段仍然会接受日期时间值,但在用户界面中时间部分将被隐藏(默认值为 true)。

    <field name="datetimefield" widget="datetime" options="{'show_time': false}" />
    
日期范围 (daterange)

此小部件允许用户从单个选择器中选择开始和结束日期。

  • 支持的字段类型:date, datetime

选项:

  • 请参见 日期字段日期和时间字段 选项

  • start_date_field:用于获取/设置日期范围起始值的字段(不能与 end_date_field 同时使用)。

    <field name="end_date" widget="daterange" options="{'start_date_field': 'start_date'}" />
    
  • end_date_field: 用于获取/设置日期范围结束值的字段(不能与 start_date_field 一起使用)。

    <field name="start_date" widget="daterange" options="{'end_date_field': 'end_date'}" />
    
剩余天数 (remaining_days)

此小部件可用于日期和日期时间字段。在只读模式下,它显示字段值与今天之间的差值(以天为单位)。在编辑模式下,小部件会变为常规的日期或日期时间字段。

  • 支持的字段类型:date, datetime

Monetary (monetary)

这是 monetary 类型字段的默认字段类型。它用于显示货币。如果选项中提供了货币字段,它将使用该字段,否则它将回退到默认货币(在会话中)

  • 支持的字段类型:monetary, float

选项:

  • currency_field:另一个字段名称,该字段应为货币的 many2one 关系。

    <field name="value" widget="monetary" options="{'currency_field': 'currency_id'}" />
    
Text (text)

这是 text 类型字段的默认字段类型。

  • 支持的字段类型:text

Handle (handle)

该字段的作用是显示为一个 handle,并允许通过拖放来重新排序各种记录。

警告

必须在记录排序的字段上指定。

警告

在同一个列表中有多个带有句柄小部件的字段是不支持的。

  • 支持的字段类型:integer

Email (email)

该字段显示电子邮件地址。使用它的主要原因是在只读模式下,它会呈现为带有正确 href 的锚标签。

  • 支持的字段类型:char

电话 (phone)

此字段显示电话号码。使用它的主要原因是它以只读模式呈现为带有正确 href 的锚标签,但仅在某些情况下:我们只想在设备可以拨打此特定号码时使其可点击。

  • 支持的字段类型:char

URL (url)

该字段以只读模式显示URL。使用它的主要原因是它被呈现为带有正确CSS类和href的锚标签。

此外,锚点标签的文本可以使用 text 属性进行自定义(它不会改变 href 值)。

  • 支持的字段类型:char

<field name="foo" widget="url" text="Some URL" />

选项:

  • website_path: (默认值:false)默认情况下,如果未设置此选项为 true,该小部件会强制(如果尚未如此)将 href 值以 "http://" 开头,从而允许重定向到数据库自己的网站。

Domain (domain)

domain 字段允许用户通过树状界面构建技术前缀域,并实时查看所选记录。在调试模式下,还提供了一个输入框,可以直接输入前缀字符域(或构建树状界面不允许的高级域)。

请注意,这仅限于 静态 域(无动态表达式,或访问上下文变量)。

  • 支持的字段类型:char

链接按钮 (link_button)

LinkButton 小部件实际上只是显示一个包含图标和文本值的 span 作为内容。链接是可点击的,并将以其值作为 URL 打开一个新的浏览器窗口。

  • 支持的字段类型:char

Image File (image)

此小部件用于将二进制值表示为图像。在某些情况下,服务器返回的是 bin_size 而不是实际的图像(bin_size 是一个表示文件大小的字符串,例如 "6.5kb")。在这种情况下,小部件将生成一个图像,其源属性对应于服务器上的图像。

  • 支持的字段类型:binary

选项:

  • preview_image:如果图像仅作为 bin_size 加载,则此选项可用于告知 Web 客户端,默认字段名称不是当前字段的名称,而是另一个字段的名称。

    <field name="image" widget="image" options="{'preview_image': 'image_128'}" />
    
  • accepted_file_extensions:用户可以从文件输入对话框中选择的文件扩展名(默认值为 "image/*"

    (cf: accept attribute on <input type="file" />)

Binary File (binary)

通用小部件,用于保存/下载二进制文件。

  • 支持的字段类型:binary

属性:

  • filename: 保存二进制文件时会丢失其文件名,因为它只保存二进制值。文件名可以保存在另一个字段中。为此,应将 filename 属性设置为视图中存在的字段。

    <field name="datas" filename="datas_fname" />
    

选项:

  • accepted_file_extensions:用户可以从文件输入对话框中选择的文件扩展名

    (cf: accept attribute on <input type="file" />)

优先级 (priority)

此小部件呈现为一组星星,允许用户单击它来选择值或不选择。例如,这对于标记任务为高优先级非常有用。

请注意,此小部件在 readonly 模式下也能工作,这是不常见的。

  • 支持的字段类型:selection

Image Attachment (attachment_image)

用于 many2one 字段的图片小部件。如果字段已设置,此小部件将渲染为带有正确 src url 的图片。此小部件在编辑或只读模式下没有不同的行为,仅用于查看图片。

  • 支持的字段类型:many2one

<field name="displayed_image_id" widget="attachment_image" />
Label Selection (label_selection)

此小部件渲染一个简单的不可编辑标签。它仅用于显示信息,而非编辑。

  • 支持的字段类型:selection

选项:

  • classes:从选择值到 CSS 类名的映射

    <field
        name="state"
        widget="label_selection"
        options="{
            'classes': {
                'draft': 'default',
                'cancel': 'default',
                'none': 'danger',
            },
        }"
    />
    
State Selection (state_selection)

这是一个专门的选择小部件。它假设记录中有一些硬编码字段,存在于视图中:stage_idlegend_normallegend_blockedlegend_done。这主要用于显示和更改项目中任务的状态,并在下拉菜单中显示附加信息。

  • 支持的字段类型:selection

<field name="kanban_state" widget="state_selection" />
State Selection - List View (list.state_selection)

在列表视图中,state_selection 字段默认显示图标旁边的标签。

  • 支持的字段类型:selection

选项:

  • hide_label: 隐藏图标旁边的标签

    <field name="kanban_state" widget="state_selection" options="{'hide_label': true}" />
    
收藏 (boolean_favorite)

此小部件根据布尔值显示为空星形或实星形。请注意,它也可以在只读模式下进行编辑。

  • 支持的字段类型:boolean

切换 (boolean_toggle)

显示一个切换开关来表示布尔值。这是 boolean 字段的一个子字段,主要用于呈现不同的外观。

  • 支持的字段类型:boolean

Stat Info (statinfo)

此部件旨在表示 stat 按钮 中的统计信息。它基本上只是一个带有数字的标签。

  • 支持的字段类型:integer, float

选项:

  • label_field:如果指定,小部件将使用 label_field 的值作为文本。

    <button
        name="%(act_payslip_lines)d"
        icon="fa-money"
        type="action"
    >
        <field
            name="payslip_count"
            widget="statinfo"
            string="Payslip"
            options="{'label_field': 'label_tasks'}"
        />
    </button>
    
Percent Pie (percentpie)

此小部件旨在表示 stat button 中的统计信息。它与 statinfo 小部件类似,但信息以 饼图 形式表示(从空到满)。请注意,该值被解释为百分比(介于 0100 之间的数字)。

  • 支持的字段类型:integer, float

<field name="replied_ratio" string="Replied" widget="percentpie" />
进度条 (progressbar)

将值表示为进度条(从 0 到某个值)

  • 支持的字段类型:integer, float

选项:

  • editable: 布尔值,决定 value 是否可编辑

  • current_value:从视图中必须存在的字段中获取当前值

  • max_value:从必须存在于视图中的字段中获取最大值

  • edit_max_value: 布尔值,用于确定 max_value 是否可编辑

  • title: 栏的标题,显示在栏的顶部

    -> 不翻译,如果术语必须翻译,请改用 title 属性(而非选项)

<field
    name="absence_of_today"
    widget="progressbar"
    options="{
        'current_value': 'absence_of_today',
        'max_value': 'total_employee',
        'editable': false,
    }"
/>
日记仪表板图表 (dashboard_graph)

这是一个更为专业的小部件,用于展示代表一组数据的图表。例如,它被用于会计仪表板的看板视图中。

它假设该字段是一组数据的JSON序列化。

  • 支持的字段类型:char

属性:

  • graph_type: 字符串,可以是 "line""bar"

    <field name="dashboard_graph_data" widget="dashboard_graph" graph_type="line" />
    
Ace 编辑器 (ace)

此小部件旨在用于文本字段。它提供了用于编辑XML和Python的Ace编辑器。

  • 支持的字段类型:char, text

徽章 (badge)

在 Bootstrap 徽章标签中显示数值。

  • 支持的字段类型:char, selection, many2one

默认情况下,徽章具有浅灰色背景,但可以通过使用 装饰 机制进行自定义。例如,在特定条件下显示红色徽章:

<field name="foo" widget="badge" decoration-danger="state == 'cancel'" />

关联字段

选择 (selection)

  • 支持的字段类型:selection

属性:

  • placeholder: 一个字符串,用于在没有选择任何值时显示一些信息

    <field name="tax_id" widget="selection" placeholder="Select a tax" />
    
单选按钮 (radio)

这是 FielSelection 的一个子字段,但专门用于将所有有效选项显示为单选按钮。

请注意,如果在many2one记录上使用,则会执行更多的rpc以获取相关记录的name_gets。

  • 支持的字段类型:selection, many2one

选项:

  • horizontal: 如果为 true,单选按钮将水平显示。

    <field name="recommended_activity_type_id" widget="radio" options="{'horizontal': true}"/>
    
Badge Selection (selection_badge)

这是 selection 字段的一个子字段,但专门用于将所有有效选项显示为矩形徽章。

  • 支持的字段类型:selection, many2one

<field name="recommended_activity_type_id" widget="selection_badge" />
Many2one (many2one)

多对一字段的默认小部件。

  • 支持的字段类型:many2one

属性:

  • can_create: 允许创建相关记录(优先于 no_create 选项)

  • can_write: 允许编辑相关记录(默认值:true

选项:

  • quick_create:允许快速创建相关记录(默认值:true

  • no_create: 阻止创建相关记录 - 隐藏 创建 “xxx”创建并编辑 下拉菜单项(默认值:false

  • no_quick_create: 防止快速创建相关记录 - 隐藏 创建 “xxx” 下拉菜单项(默认值:false

  • no_create_edit: 隐藏 创建和编辑 下拉菜单项(默认值:false

  • create_name_field:在创建相关记录时,如果设置了此选项,create_name_field 的值将使用输入的值填充(默认值:name

  • always_reload: 布尔值,默认为 false。如果为 true,该部件将始终执行额外的 name_get 以获取其名称值。这用于 name_get 方法被重写的情况(请不要这样做)。

  • no_open: 布尔值,默认为 false。如果设置为 true,则在点击 many2one 字段时(在只读模式下)不会重定向到该记录。

<field name="currency_id" options="{'no_create': true, 'no_open': true}" />
Many2one Barcode (many2one_barcode)

many2one 字段的小部件允许从移动设备(Android/iOS)打开摄像头以扫描条形码。

允许用户使用原生摄像头扫描条形码的 many2one 字段特化。然后使用 name_search 来搜索该值。

如果设置了此小部件且用户未使用移动应用程序,它将回退到常规的 many2one (Many2OneField)

  • 支持的字段类型:many2one

Many2one Avatar (many2one_avatar)

此小部件仅支持指向继承自 image.mixin 的模型的 many2one 字段。在只读模式下,它会在 display_name 旁边显示相关记录的图像。请注意,在这种情况下,display_name 不是可点击的链接。在编辑模式下,它的行为与常规的 many2one 完全相同。

  • 支持的字段类型:many2one

Many2one Avatar User (many2one_avatar_user)

此小部件是 Many2OneAvatar 的特化版本。当点击头像时,我们会打开与相应用户的聊天窗口。此小部件只能设置在指向 res.users 模型的 many2one 字段上。

  • 支持的字段类型:many2one`(指向 `res.users

Many2one Avatar Employee (many2one_avatar_employee)

many2one_avatar_user 相同,但适用于指向 hr.employeemany2one 字段。

  • 支持的字段类型:many2one`(指向 `hr.employee

Many2many (many2many)

many2many 字段的默认小部件。

  • 支持的字段类型:many2many

属性:

  • mode: 字符串,默认显示的视图

  • domain: 将数据限制在特定领域

选项:

  • create_text:允许自定义添加新记录时显示的文本

  • link: 用于确定是否可以将记录添加到关系中的域(默认值:true)。

  • unlink: 确定是否可以从关系中删除记录的域(默认值:true)。

Many2many Binary File (many2many_binary)

此小部件帮助用户同时上传或删除一个或多个文件。

注意,此小部件特定于模型 ir.attachment

  • 支持的字段类型:many2many

选项:

  • accepted_file_extensions:用户可以从文件输入对话框中选择的文件扩展名

    (cf: accept attribute on <input type="file" />)

Many2many Tags (many2many_tags)

many2many 字段显示为标签列表。

  • 支持的字段类型:many2many

选项:

  • create: 用于确定是否可以创建新标签的域(默认值:true)。

    <field name="category_id" widget="many2many_tags" options="{'create': [['some_other_field', '>', 24]]}" />
    
  • color_field: 一个数值字段的名称,该字段应存在于视图中。将根据其值选择颜色。

    <field name="category_id" widget="many2many_tags" options="{'color_field': 'color'}" />
    
  • no_edit_color:设置为 true 以移除更改标签颜色的功能(默认值:false)。

    <field name="category_id" widget="many2many_tags" options="{'color_field': 'color', 'no_edit_color': true}" />
    
  • edit_tags:设置为 true 以允许通过点击标签来更新与标签相关的记录。(默认值:false)。

    <field name="category_id" widget="many2many_tags" options="{'edit_tags': true}" />
    
Many2many Tags - Form View (form.many2many_tags)

many2many_tags 小部件在表单视图中的特化版本。它包含一些额外的代码,允许编辑标签的颜色。

  • 支持的字段类型:many2many

Many2many Tags - Kanban View (kanban.many2many_tags)

many2many_tags 小部件在看板视图中的特化。

  • 支持的字段类型:many2many

Many2many Checkboxes (many2many_checkboxes)

此字段显示一组复选框,允许用户选择部分选项。请注意,显示值的数量限制为 100。此限制不可自定义。它仅用于处理极端情况,即此小部件错误地设置在具有巨大关联模型的字段上。在这些情况下,列表视图更为合适,因为它允许分页和过滤。

  • 支持的字段类型:many2many

One2many (one2many)

one2many 字段的默认小部件。它通常会在子列表视图或子看板视图中显示数据。

  • 支持的字段类型:one2many

选项:

  • create: 用于确定是否可以创建相关记录的域(默认值:true)。

  • delete: 用于确定是否可以删除相关记录的域(默认值:true)。

    <field name="turtles" options="{'create': [['some_other_field', '>', 24]]}" />
    
  • create_text: 用于自定义“添加”标签/文本的字符串。

    <field name="turtles" options="{'create_text': 'Add turtle'}" />
    
状态栏 (statusbar)

这是表单视图特有的字段。它是许多表单顶部的栏,代表一个流程,并允许选择特定状态。

  • 支持的字段类型:selection, many2one

Reference (reference)

reference 字段是 select(用于模型)和 many2one 字段(用于其值)的组合。它允许在任意模型上选择一条记录。

  • 支持的字段类型:char, reference

选项:

  • model_field: 包含可选择记录模型的 ir.model 的名称。当设置此选项时,reference 字段的选择部分将不会显示。

小部件

Ribbon (web_ribbon)

此小部件在看板卡片或表单视图表的右上角显示一条丝带,例如,用于指示已归档的记录。

<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger"/>

属性:

  • title: 在功能区中显示的文本。

  • tooltip: 功能区工具提示中显示的文本。

  • bg-class: 用于设置丝带上的类名,通常用于定义丝带的颜色。

周几 (week_days)

此小部件显示一周中各天的复选框列表,每天一个复选框,允许用户选择其中的一部分选项。

<widget name="week_days" />

客户端操作

客户端动作是一个可以作为主元素显示在网页客户端中的组件,占据导航栏下方的所有空间,就像 act_window_action 一样。当你需要一个与现有视图或特定模型没有紧密关联的组件时,这非常有用。例如,讨论应用程序就是一个客户端动作。

客户端操作是一个术语,其含义因上下文而异:

  • 从服务器的角度来看,它是一个模型 ir_action 的记录,具有一个类型为 char 的字段 tag

  • 从 web 客户端的角度来看,它是一个 Owl 组件,注册在动作注册表中,与其标签使用相同的键

每当菜单项与客户端操作相关联时,打开它只需从服务器获取操作定义,然后在操作注册表中查找其标签以获取组件定义。该组件随后将由操作容器渲染。

添加客户端操作

客户端动作是一个组件,它将控制导航栏下方的屏幕部分。定义客户端动作就像创建一个 Owl 组件并将其添加到动作注册表中一样简单。

import { registry } from "@web/core/registry";
class MyClientAction extends Component { ... }
registry.category("actions").add("my-custom-action", ClientAction);

然后,在Web客户端中使用客户端操作,我们需要创建一个客户端操作记录(一个 ir.actions.client 模型的记录),并设置正确的 tag 属性:

<record id="my_client_action" model="ir.actions.client">
    <field name="name">Some Name</field>
    <field name="tag">my-custom-action</field>
</record>