How to create field widget using Owl in Odoo 16

How to create field widget using Owl in Odoo 16

Widget in Odoo is basically one of the  building block of the Odoo User Interface. Odoo has many widgets to perform different functionalities such as remaining_days, color_picker, char_emojis, priority, many2many_tags, boolean_toggle etc.

In Odoo 16 the widgets are migrated to OWL framework. OWL is a declarative component system, loosely inspired by Vue and React developed in house by Odoo SA. The work on OWL framework started a few years back and Odoo was slowly migrating various parts of Odoo source code from the old one to the new OWL framework.

In this blog we are discussing about creating widget. Below is the basic step for creating a new widget

For creating a widget we have to first import and extend the component. Components are like functions that returns HTML elements. In Owl we use class components, they are independent and reusable.

1. Import Component from Owl library

/** @odoo-module **/

import { Component } from"@odoo/owl";


2. Import Registry

import { registry } from"@web/core/registry";


3. Extends the component and creates new component class

export class MyNewWidget extends Component {    
​setup() {       
			​// initialize component here
​}
}


4. Declaring the template for the widget

#The Good practice for naming the template is below because this prevents the collision between Odoo addons MyNewWidget.template = "addon_name.MyNewWidget";


5. Importing standardFieldProps

import { standardFieldProps } from"@web/views/fields/standard_field_props";
MyNewWidget.props = {   
​...standardFieldProps,
placeholder: { type: String, optional:true },
};

Below are some default standardFieldProps seen in odoo/addons/web/static/src/views/fields/standard_field_props.js

/** @odoo-module **/

export const standardFieldProps = {   
​id: { type: String, optional:true },   
​name: { type: String, optional:true },   
​readonly: { type: Boolean, optional:true },   
​record: { type: Object, optional:true },   
​type: { type: String, optional:true },   
​update: { type: Function, optional:true },   
​value:true,
​decorations: { type: Object, optional:true },   
​setDirty: { type: Function, optional:true },
};

6. Extract attribute value from props

MyNewWidget.extractProps = ({ attrs }) => {    
​return {
​#this placeholder can be displayed in the template using t-att-placeholder="props.placeholder"
​placeholder: attrs.placeholder,   
​};
};

7. Adding widget display name

MyNewWidget.displayName = _lt("My Widget");

8. Add supported field types for the widget

MyNewWidget.supportedTypes = ["float", "int"];

9. Adding the widget to the registry of category fields

registry.category("fields").add("new_widget", MyNewWidget);


10. Template located in the xml file

<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
    <t t-name="addon_name.MyNewWidget" owl="1">       
​<span t-if="props.readonly" t-esc="props.value"/>       
​<input t-else="" t-att-value="props.value" t-att-placeholder="props.placeholder" class="o_input"/>   
​ </t>
</templates>


11. Add the JS and XML file path to manifest of the module

'assets': {
		​'web.assets_backend': [
			​'module_name/static/src/js/widget_file.js',
​'module_name/static/src/xml/widget_file.xml', ​]
},


12. Use the widget in a field

<field name="note" widget="new_widget" placeholder="note......."/>

We can also create a new widget by extending the already created widget. Below is the steps for extending the widget.

1. Import the widget that you want to extend

import { MyNewWidget} from"@module_name/static/src/js/MyNewWidget";

2. Extend the imported widget component

exportclass MyNewWidgetExtend extends MyNewWidget {
​setup() {
​super.setup();
​}
}

3. Define the template

MyNewWidgetExtend.template = "module_name.MyNewWidgetExtend"

4. Adding to registry

registry.category("fields").add("new_widget_extend", MyNewWidgetExtend);

5. Template in xml

<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
    <t t-name="module_name.MyNewWidgetExtend" owl="1">       
​<span t-if="props.readonly" t-esc="props.value"/>       
​<input t-else="" t-att-value="props.value" class="o_input"/>   
​ </t>
</templates>

We can create various types of widgets with various functionalities by using the field widgets in Odoo, like triggering a specific action on barcode scan etc.

Mohammed Shahil 26 November, 2022
Sign in to leave a comment