Enable Dark Mode!
how-to-build-responsive-user-interfaces-in-odoo-19-with-owl.jpg
By: Abhijith CK

How to Build Responsive User Interfaces in Odoo 19 with OWL

Technical Odoo 19 Owl

In the case of modern ERP applications, however, there is not much sense in having an inflexible UI for all users. On desktop computers, users expect data-packed views in lists and in forms that use several columns in order to increase data input velocity. On mobile devices, users need card-like views and simplified forms.

While responsive CSS based on media queries or Bootstrap grid can help with simple UI modifications, sometimes completely different UI components and view architectures are needed.

In this guide, we will consider how to achieve dynamic UI customization depending on the device used by the user in Odoo 19 using OWL and backend Actions services.

The Architectural Options

When building device-specific interfaces in Odoo 19, you have two primary options depending on the scope:

  1. Component Level Switching (Frontend): Dynamically switching and rendering entirely different OWL components based on reactive screen size state.
  2. Action Level Switching (Backend): Override the action calls (window actions) for different default views (Kanban for mobile view and List for desktop view).

1. Component-Level Switching with OWL

The Odoo version 19 has ui service which consists of reactive properties of the client interface and is called isSmall. In the framework OWL, isSmall is a reactive boolean property that becomes true when the width of the screen corresponds to the width of mobile devices (smaller than 768px).

We will make a parent component that reacts to the changes of ui service and uses our external XML templates.

The JavaScript Component (components.js)

import {Component} from "@odoo/owl";
import {useService} from "@web/core/utils/hooks";
import {registry} from "@web/core/registry";
class MobileDashboard extends Component {
    static template = "your_module_name.MobileDashboard";
}
class DesktopDashboard extends Component {
    static template = "your_module_name.DesktopDashboard";
}
export class DeviceSwitcher extends Component {
    static template = "your_module_name.DeviceSwitcher";
    static components = {MobileDashboard, DesktopDashboard};
    setup() {
        // Inject Odoo's UI service
        this.ui = useService("ui");
    }
}
// Register custom component in the client action registry
registry.category("actions").add("device_specific_dashboard",DeviceSwitcher);

The QWeb Template (components.xml)

<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
 <!-- Mobile-Specific View -->
 <t t-name="your_module_name.MobileDashboard">
     <div class="p-3 bg-light rounded text-center">
     <h4 class="text-primary">
        <i class="fa fa-mobile me-2"/>Mobile Dashboard</h4>
        <p class="text-muted">Touch-optimized widgets, quick-action buttons, and compact cards.</p>
         <button class="btn btn-primary w-100 py-3 shadow-sm">
        <i class="fafa-plus me-2"/>Quick Create Record
    </button>
 </div>
 </t>
 <!-- Desktop-Specific View -->
 <t t-name="your_module_name.DesktopDashboard">
    <div class="p-4 bg-white border rounded shadow-sm">
        <div class="d-flex justify-content-between align-items-center mb-3">
            <h3 class="text-dark"><i class="fa fa-desktop me-2"/>Desktop Command Center</h3>
            <button class="btn btn-secondary btn-sm">Refresh Metrics</button>
        </div>
        <p>Comprehensive split-pane layout, data grids, and hovering action toolbars.</p>
        <div class="row text-center mt-3">
            <div class="col-4 border-end"><strong>Active:</strong>42</div>
            <div class="col-4-end"><strong>Pending:</strong>12</div>
            <div class="col-4"><strong>Completed:</strong>256</div>
         </div>
    </div>
 </t>
 <!-- Main Device Switcher Parent Component -->
 <t t-name="your_module_name.DeviceSwitcher">
     <div class="device-switcher-container">
         <t t-if="ui.isSmall">
             <MobileDashboard/>
         </t>
         <t t-else="">
            <DesktopDashboard/>
         </t>
     </div>
 </t>
 </templates>

The Action Template (your_module_actions.xml)

<?xml version="1.0" encoding="utf-8"?>
<odoo>
   <!-- Root Menu for the Switcher -->
   <menuitem id="menu_device_switcher_root" name="Device Switcher" sequence="100"/>
   <!-- Client Action for OWL Component -->
   <record id="action_device_switcher_dashboard" model="ir.actions.client">
       <field name="name">Device Specific Dashboard</field>
       <field name="tag">device_specific_dashboard</field>
   </record>
   <!-- Menu Item under Root -->
   <menuitem id="menu_device_switcher_dashboard"
             name="Dashboard"
             parent="menu_device_switcher_root"
             action="action_device_switcher_dashboard"
             sequence="10"/>
</odoo>

2. Action-Level Switching (Backend Model Override)

However, there may be cases where you may want Odoo standard views, such as "sale.order list" or "kanban," to alter their operation. In case the mobile user clicks "Sales Orders", then you would like him/her to land on the "Kanban View," whereas the desktop user should land on the "List View."

This can be done by modifying the Python function that resolves the window action with respect to the sequence of view modes.

from odoo import models, api
 class SaleOrder(models.Model):
    _inherit = 'sale.order'
    @api.model
    def action_view_sales_orders(self):
        """prioritize Kanban view on mobile devices and List view on desktop environments."""
    # Fetch the original action dict
        action = self.env.ref('sale.action_orders').read()[0]
        # Check client context set by Odoo's web client
        is_mobile = self.env.context.get('is_mobile', False)
        if is_mobile:
            # Shift 'kanban' to the primary view mode
            action['view_mode'] = 'kanban,list,form,calendar'
        else:
            #Default desktop layout prioritizes the tree (list) view
  action['view_mode'] = 'list,kanban,form,calendar'
 
        return action

To make sure that is_mobile is consistently available within your RPCs and context dictionary, the Odoo web client will always make sure that the device is being passed in the session configuration. But if you are calling an action through JavaScript, pass it explicitly:

this.actionService.doAction("sale.action_orders",{
                additionalContext: { 
                    is_mobile: this.ui.isSmall,
                }
 });

3. Registering the Frontend Assets

For Odoo 19 to load your new OWL components and JS files, they must be registered in your module's __manifest__.py under the appropriate web assets bundle.

{
    'name': 'Device-Specific UI Switcher',
    'version': '19.0.1.0.0',
    'category': 'Tooling',
    'depends': ['web'],
    'data': [
        'views/your_module_actions.xml',
    ],
    'assets': {
        'web.assets_backend': [
            'your_module_name/static/src/components/components.js',
            'your_module_name/static/src/components/components.xml',
        ],
    },
    'installable': True,
    'application': False,
 }

Best Practices for Mobile vs. Desktop UI/UX in Odoo

  • CSS-only hiding is not advised for heavy components: Although using classes like d-none d-md-block hides the component from rendering visually, the HTML element will be created along with the initialization of the JavaScript state. It is better to use OWL's conditional rendering (t-if).
  • Network Load Control: Many mobile users are on networks with higher latency. Mobile-specific components should not perform heavy table requests. Only those fields that are needed for the mobile card view should be requested.
  • Touch Target Size: Any action within mobile-specific components should have a touch target size equal to 48x48px.

Responsive interfaces in Odoo 19 go beyond adapting screen layouts to varying display sizes. Users working from a desktop or mobile phone may differ in their expectations, workflows, and ways of interacting with software, which should be taken into account to enhance usability and increase productivity.

Using the owl's reactive ui service allows you to switch between various components at runtime based on the user's device type and, therefore, create device-specific interfaces. In situations where view behavior should be changed, for example, by showing Kanban views on mobile and List views on desktop, backend actions customization offers an elegant way to do so. Using front-end component rendering and back-end actions customization together enables you to provide a device-aware interface without repeating business logic and having two applications.

Adhering to best practices like conditional component rendering, reducing excessive data loading, and making touch interfaces enables you to create efficient interfaces. Odoo 19 is being developed using the OWL framework, and the above approaches allow you to create adaptive interfaces in an Odoo application.

To read more about How to Use OWL Components in Odoo 19, refer to our blog How to Use OWL Components in Odoo 19.


Frequently Asked Questions

What is the ui.isSmall property in Odoo 19?

ui.isSmall is a reactive variable that is available within Odoo's UI service inside the OWL framework. It becomes true automatically whenever the application is opened on a small-screen device, such as phones and tablets, and developers can create separate views for smaller devices using this variable.

Why should I use OWL component switching instead of CSS media queries?

CSS media queries affect only the way elements look. The elements are drawn, and the logic of their JavaScript is executed. Conditional rendering in OWL by using t-if makes sure that unnecessary elements arenโ€™t created at all, saving both memory and performance, particularly when it comes to mobile devices.

When should I choose frontend component switching over backend action switching?

Choose the frontend component switching strategy in case you need varying layouts and widgets within one page or client action. Use the backend action switching technique in case you need Odoo to load different default views based on users' devices (for example, Kanban, List, or Form views). Both methods can be used together in many projects for the best result.

Does ui.isSmall detect the device type or the screen size?

The ui.isSmall property depends on the dimensions of the viewport, not the actual device being used. This will even be true for a browser running on a desktop computer if its window is small.

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



0
Comments



Leave a comment



WhatsApp