Odoo provides a wide range of field widgets to display different types of data in the user interface. However, there may be cases where you need to customize an existing field widget or create a new one to meet your specific needs.
Example
Let's create a custom boolean field widget called boolean_badge. This widget will display a badge with the text "Yes" or "No," depending on the value of the field.
To create the widget, we first need to create a new JavaScript file in our module's static/src/js directory. In this file, we will import the standardFieldProps object from the @web/views/fields/standard_field_props module. This object contains a set of standard props that are common to all field widgets. We will also import the Component class from the Owl library.
import { registry } from "@web/core/registry";
import { standardFieldProps } from "@web/views/fields/standard_field_props";
const { Component } = owl;
Next, we need to define a new class called BooleanBadge that extends the Component class. This class will contain the logic for rendering the badge and handling user interactions.
class BooleanBadge extends Component {
setup(){
this.trueValue = 'Yes'
this.falseValue = 'No'
this.trueColor = 'green'
this.falseColor = 'red'
this.defaultColor = 'white'
}
updateValue(val){
this.props.update(val);
}
}
In the setup() method, we are setting the default values for the trueValue, falseValue, trueColor, falseColor, and defaultColor props. We can also use the setup() method to initialize any other state that the widget needs.
The updateValue() method is called when the value of the field changes. This method updates the state of the widget and re-renders it.
Now that we have defined the widget class, we need to register it with Odoo. To do this, we add the following code to the end of the JavaScript file.
BoolBadge.template = "BoolBadge"
BoolBadge.props = standardFieldProps
BoolBadge.supportedTypes = ["boolean"]
registry.category("fields").add("boolean_badge",BoolBadge)
The template prop specifies the name of the template file that will be used to render the widget. The props prop specifies the props that are accepted by the widget. The supportedTypes prop specifies the types of fields that the widget can be used with.
Finally, we need to create the template file for the widget. Create a new file in the static/src/xml directory of your module called BooleanBadge.xml. In this file, add the following code:
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="BooleanBadge" owl="1">
<span class="badge rounded-pill m-2 p-2 border"
t-att-class="props.value ? 'text-white' : 'text-black'
t-esc="trueValue"
t-attf-style="background-color: {{ props.value ? trueColor : defaultColor}}"
t-on-click="() => this.updateValue(true)"/>
<span class="badge rounded-pill m-2 p-2 border"
t-att-class="props.value ? 'text-black' : 'text-white'"
t-esc="falseValue"
t-attf-style="background-color: {{ props.value ? defaultColor : falseColor}}"
t-on-click="() => this.updateValue(false)"/>
</t>
</templates>
This template will display a badge with the text "Yes" or "No" depending on the value of the field. The background color of the badge will be determined by the trueColor or falseColor prop, depending on the value of the field.
Once you have created the JavaScript and XML files for the widget, you can use them in your Odoo views. To add the widget to a field, simply add the following attribute to the field:
widget="boolean_badge"
Now, let’s add this widget to the test field inside the product template page.
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="product_template_only_form_view" model="ir.ui.view">
<field name="name">product.template.inherit.coc</field>
<field name="model">product.template</field>
<field name="inherit_id"
ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<field name="detailed_type" position="after">
<field name="test_field" widget="boolean_badge"/>
</field>
</field>
</record>
</odoo>
Now, the field looks like as follows
Extending the BooleanBadge widget to add options
You can extend the BooleanBadge widget to add options that allow you to customize the appearance of the badge and the text that is displayed. For example, you could add an option to change the size of the badge, the font of the badge text, or the border of the badge.
To extend the BooleanBadge widget to add options, you can create a new JavaScript file in the static/src/js directory of your module. Then, Import the BooleanBadge widget from your existing module. Define a new class that extends the BooleanBadge widget. Add a new prop to your widget to store the value of the option. Implement any custom behavior for your option, and register your new widget in the registry module.
Example
/** @odoo-module */
import { registry } from "@web/core/registry";
import { standardFieldProps } from "@web/views/fields/standard_field_props";
import { BoolBadge } from "@custom_widget/js/bool_badge";
export class CustomBoolBadge extends BoolBadge {
setup() {
super.setup();
const options = this.props.options || {};
this.trueValue = options.trueValue || 'Yes';
this.falseValue = options.falseValue || 'No';
this.trueColor = options.trueColor || 'green';
this.falseColor = options.falseColor || 'red';
this.defaultColor = options.defaultColor || 'white';
}
}
CustomBoolBadge.props = {
...standardFieldProps,
options: { type: Object, optional: true}
}
CustomBoolBadge.extractProps = ({attrs}) => {
return {options: attrs.options}
}
registry.category("fields").add("custom_bool_badge", CustomBoolBadge);
To use the CustomBoolBadge widget, you can add it to a view in the same way that you would add any other field widget. For example, the following code would add a CustomBoolBadge widget to the test_field field:
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="product_template_only_form_view" model="ir.ui.view">
<field name="name">product.template.inherit.coc</field>
<field name="model">product.template</field>
<field name="inherit_id"
ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<field name="detailed_type" position="after">
<field name="test_field" widget="custom_bool_badge" options="{'trueColor': 'blue', 'trueValue': 'Yes',
'falseColor': 'yellow', 'falseValue': 'No'}"/>
</field>
</field>
</record>
</odoo>
In this, we have given trueColor as blue and falseColor as yellow and corresponding values. Let's see the result.
Now we can see the color has changed to blue and yellow, respectively.
This is how we can extend and add features to the existing field widgets in Odoo 16.