Enable Dark Mode!
how-to-add-a-many2many-selection-field-in-a-custom-dialog-popup-in-odoo19-using-owl.jpg
By: Yadu Krishna N P

How to add a Many2many Selection Field in a Custom Dialog Popup in Odoo19 Using OWL

Technical Odoo 19 Owl

Looking to improve your Odoo 19 modules with a modern, easy-to-use Many2many selection field in a custom dialog popup? Whether you want to create a multi-product selector for sales orders or allow users to choose multiple records from any model, Odoo 19’s OWL framework provides a powerful, clean, and developer-friendly solution.

In this guide, we’ll show you how to build a custom dialog popup with a Many2many selection field in Odoo 19 using OWL. This approach combines flexibility with a great user experience. Through clear, step-by-step code explanations, you’ll learn how to use OWL’s reactive state management and Odoo’s UI components to create fast, elegant, and highly interactive selection dialogs. By the end, you’ll have a reusable pattern that you can easily adapt for different use cases, helping you create polished, modern interfaces in Odoo 19. Let’s get started!

Prerequisites

Before moving forward with the code, ensure you have

  • an active Odoo 19 environment,
  • Familiarity with Odoo module development and basic knowledge of OWL (Odoo Web Library).
  • A module structure setup with JavaScript, XML templates, and client action.

Code Breakdown

Using a Many2many field, we are going to build a custom dialogue popup that allows users to select multiple products from the product.template model. Three main parts comprise the implementation: a client action definition, an OWL template, and a JavaScript component. Let's go through each of them.

1. JavaScript Component (multiselection_dialog.js)

The OWL component that operates the Many2many selection field is defined in this JavaScript file.

/** @odoo-module **/
import { registry } from "@web/core/registry";
import { Component, useState } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
import { MultiRecordSelector } from "@web/core/record_selectors/multi_record_selector";
export class MultiSelectionDialog extends Component {
   static template = "your_module_name.multiselection_dialog";
   static components = { MultiRecordSelector };
   setup() {
       this.nameService = useService("name");
       this.state = useState({
           resIds: [],
           displayNames: [],
           model: "product.template",
       });
   }
   get domain() {
       return [["active", "=", true]];
   }
   async onSelectionUpdate(resIds) {
       const names = await this.nameService.loadDisplayNames(
           this.state.model,
           resIds
       );
       this.state.resIds = resIds;
       this.state.displayNames = Object.values(names);
   }
}
// Register client action
registry.category("actions").add(
   "multi_selection_dialog",
   MultiSelectionDialog
);

The code imports the necessary Odoo and OWL modules, such as registry for client action registration, useService for Odoo service access, Component and useState from OWL for reactive component construction, and MultiRecordSelector for a Many2many-style record selection widget.

Component Definition: The template your_module_name.multiselection_dialog is linked to the MultiSelectionDialog class, which is an extension of Component. Additionally, MultiRecordSelector is declared as a sub-component so that the OWL template can use it.

Setup Method: The component is initialized by:

  • retrieving display names for particular records by using the name service.
  • The chosen record IDs (resIds), their display names, and the target model (product.template) are stored in a reactive state object created with useState.

Domain Getter: To limit the selectable records, the domain getter defines a filter ([="active", "=", true]]) that permits only active products. Depending on the needs of the business, this can be changed.

onSelectionUpdate Method: Anytime the selection is altered, this asynchronous method is called. It updates the component state with the new IDs and matching names after using the name service to retrieve display names for the chosen record IDs.

Registry: Makes the MultiSelectionDialog component callable from menus, buttons, or server actions by registering it in Odoo's action registry as a client action called multi_selection_dialog.

2. OWL Template (multiselection_dialog.xml)

The OWL template defines the structure of the dialog popup.

<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
   <t t-name="your_module_name.multiselection_dialog">
       <div class="o_dialog_container p-3">
           <MultiRecordSelector
               resModel="state.model"
               resIds="state.resIds"
               domain="domain"
               fieldString="'Products'"
               placeholder="'Select Products'"
               update.bind="onSelectionUpdate"
           />
       </div>
   </t>
</templates>

Template Definition: An OWL template called multi_selection.multiselection_dialog is defined in the XML. This template is in charge of rendering the dialogue content and displays a Many2many-style product selection field using the MultiRecordSelector component.

Structure: To guarantee appropriate spacing and styling within a popup dialogue, the outer <div> makes use of Odoo dialog-related classes (o_dialog_container p-3).

Attributes:

  • resModel: Specifies the model being queried (product.template) by binding to state.model from the JavaScript component.
  • resIds: Attached to the state.resIds, which stand for the record IDs that are currently selected. This maintains the UI's alignment with the reactive state of the component.
  • domain: Enables filtering of the record list (e.g., displaying only active products) by connecting to the domain getter defined in the JavaScript component.
  • fieldString: Sets "Products" as the field label that appears in the user interface.
  • placeholder: Describes the "Select Products" placeholder text that appears when no records are chosen.
  • update.bind: Ensures that the state is updated each time the user modifies the selection by binding the onSelectionUpdate method from the JavaScript component.

3. Client Action (client_action.xml)

This XML defines the client action that triggers the dialog popup.

<odoo>
   <record id="action_multi_product_selection" model="ir.actions.client">
       <field name="name">Select Products</field>
       <field name="tag">multi_selection_dialog</field>
   </record>
   <menuitem id="menu_multi_selection" name="Multi Product Selection" action="action_multi_product_selection"/>
</odoo>

Action Definition: Uses the ID action_multi_product_selection to create a client action.

Fields:

  • name: Sets "Select Products" as the action's display name.
  • tag: Links this action to a matching JavaScript client component by referencing the multi_selection_dialog client action tag.
  • binding_model_id: Makes the action accessible from Sales Order views by binding it to the sale.order model (e.g., via an action or button).
  • target: When set to new, the client action opens in a modal dialogue (popup) rather than leaving the current view.

Implementation

1. Module Structure

Ensure your odoo module (your_module_name) includes:

  • A static/src/js/ folder for the JavaScript file.
  • A static/src/xml/ folder for the OWL template.
  • A views/ folder for the client action XML.

2. File Placement

  • Save the JavaScript code in static/src/js/multiselection.js.
  • Save the template in static/src/xml/multiselection.xml.
  • Save the client action in views/client_action.xml.

3. Manifest Update

Include the JavaScript and XML files in your module’s __manifest__.py:

{
   "name": "Multi Selection Dialog (OWL)",
   "depends": ["sale_management"],
   "data": [
       "views/multi_client_action.xml",
   ],
   "assets": {
       "web.assets_backend": [
           "multi_selection/static/src/js/multiselection_dialog.js",
           "multi_selection/static/src/xml/multiselection_dialog.xml",
       ],
   },
   "installable": True,
   "application": False,
}

4. Install/Update Module

Install or upgrade your module in Odoo to register the action.

5. Test Action

In the Odoo interface, navigate to a sales order and trigger the "Choose Product" action to see the dialog pop-up with the Many2many selection field.

Customization Tips

  • Change the Model: Update this.state.state.model in setup() to another model (e.g., res.partner) to select different types of records.
  • Adjust the Domain: Update the domain getter to filter records based on your criteria (e.g., [["active", "=", true]] for active records).
  • Styling: Enhance the dialog’s appearance by adding CSS to your module’s assets.
  • Saving Selections: Extend the onSelectionUpdate(resIds) method to save selected resIds to a field on the sale.order model or perform other actions.

A Many2many selection field implemented in a custom dialog popup using OWL is an engaging and effective way of interacting with the user in Odoo 19. By utilizing the MultiRecordSelector component and OWL's reactive state management, developers can create simple, dynamic, and user-friendly interfaces with very little effort. In this way, the selection of multiple records in a modal dialog has been made easier for users, and thus the overall efficiency of the workflow has been increased.

The implementation given above is a good starting point for the selection of multiple records, and it is also a good foundation that can be extended or adapted easily to comply with the requirements of different models and businesses. Little changes like changing the target model, refining domains, or persisting selected records can help you to use this solution for a wide range of use cases. OWL will, regardless of you creating advanced selection dialogs or custom popups, help you in building clean, modern UI components that enhance your Odoo modules.

Do more exploration, do more experimenting with features, and make the most out of OWL and Odoo's JavaScript framework by building strong, interactive features that will be the next level of your Odoo development.

To read more about How to Add a Many2many Selection Field in a Custom Dialog Popup in Odoo 18 Using OWL, refer to our blog How to Add a Many2many Selection Field in a Custom Dialog Popup in Odoo 18 Using OWL.


Frequently Asked Questions

Can this Many2many dialog be reused for other models besides product.template?

Yes. The dialog is fully reusable. You only need to change the model value in the component’s state (for example, account.move, res.partner, or any custom model). You can also dynamically pass the model name through action context if you want the same dialog to work for multiple use cases.

How can I save the selected records to a field on a model?

You can extend the onSelectionUpdate method to call the ORM service and write the selected resIds to a Many2many field. For example, use useService(“orm”) and call orm.write() on the active record ID obtained from the action context.

Is it possible to open this dialog from a button instead of a menu item?

Absolutely. You can trigger the client action from a form view button by defining an ir.actions.client action and referencing it in the button’s action attribute. This is commonly done in Sales Orders, Purchase Orders, or custom forms.

How can I pre-fill the dialog with already selected records?

You can initialize state.resIds in the setup() method using values passed through the action context. For example, if the current record already has a Many2many field populated, you can read those IDs and load them into the dialog when it opens.

Can I apply advanced filters like categories, companies, or custom conditions?

Yes. The domain getter can be fully customized. You can include category filters, company-based restrictions, or even compute dynamic domains based on user input, context values, or the active record.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, KINFRA Techno Park
Kakkanchery, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message