Zalino Logo white

Odoo POS 18 – How to add Custom PoPup Window & Click Event in Odoo Point of Sale Version 18

Odoo POS Dashboard Image
Odoo POS 18, how to add custom PoP Up window on button click event

First of all create following files inside app directory:

  • custom_button.xml
  • custom_button.js
  • text_input_popup.xml
  • text_input_popup.js
Directory Structure of your custom app

your_app/
├── __init__.py
├── __manifest__.py
├── static/
│         └── src/
│                 └── app/
│                         └── custom_button/
│                                 └── custom_button.xml
│                                 └── custom_button.js
│                         └── custom_popup/
│                                 └── text_input_popup.xml
│                                 └── text_input_popup.xml
└── README.md

Add The xml code inside custom_button.xml
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="pos_custom.ControlButtons" t-inherit="point_of_sale.ControlButtons" t-inherit-mode="extension">

<xpath expr="//button[@class='btn btn-light btn-lg flex-shrink-0 ms-auto']" position="before">
<button class="btn btn-light btn-lg flex-shrink-0 ms-auto"
t-on-click="() => this.onClickPopupSingleField()">Custom Button</button>
</xpath>


<xpath expr="//t[@t-if='props.showRemainingButtons']/div/OrderlineNoteButton" position="after">
<button class="btn btn-secondary btn-lg py-5" t-on-click="() => this.onClickPopupSingleField()">
<i class="fa fa-pencil-square me-1" role="img" aria-label="Custom Alert" title="Custom Alert"/>Custom
Button
</button>
</xpath>

</t>
</templates>
Add the js code to handle click event inside custom_button.js
your_app>static>src>app>custom_button>custom_button.js:

/**@odoo-module **/
import { AlertDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
import { _t } from "@web/core/l10n/translation";
import { ControlButtons } from "@point_of_sale/app/screens/product_screen/control_buttons/control_buttons";
import { patch } from "@web/core/utils/patch";
import { TextInputPopup } from "@pos_custom/app/custom_popup/text_input_popup";

patch(ControlButtons.prototype, {
    async onClickPopupSingleField() {
        this.dialog.add(TextInputPopup, {
            title: _t("To Apply Discount, Enter CNIC & Code"),
            placeholder: _t("Enter CNIC"),
            getPayload: async (code,code2) => {
                let cnic = code.trim();

               console.log('Ready to use cnic: ',cnic);
            },
        });
    },
});

    
Add The xml code inside text_input_popup.xml
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="pos_custom.TextInputPopup">
<Dialog title="props.title">
<t t-foreach="props.buttons" t-as="button" t-key="button_index">
<button t-on-click="() => this.buttonClick(button)" type="button"
t-attf-class="btn btn-lg me-2 mb-2 toggle-button {{button.isSelected? 'btn-primary' : 'btn-secondary'}} lh-lg">
<t t-esc="button.label"/>
</button>
</t>
<textarea t-att-rows="props.rows" class="form-control form-control-lg mx-auto" type="text"
t-model="state.inputValue" t-ref="input" t-att-placeholder="props.placeholder"
t-on-keydown="onKeydown"/>
<t t-set-slot="footer">
<button class="btn btn-primary btn-lg lh-lg o-default-button" t-on-click="confirm">Apply</button>
<button class="btn btn-secondary btn-lg lh-lg o-default-button" t-on-click="close">Discard</button>
</t>
</Dialog>
</t>
</templates>
Add the js code to handle click event inside text_input_popup.js
your_app>static>src>app>custom_popup>text_input_popup.js:

import { Component, onMounted, useRef, useState } from "@odoo/owl";
import { Dialog } from "@web/core/dialog/dialog";

export class TextInputPopup extends Component {
    static template = "pos_custom.TextInputPopup";
    static components = { Dialog };
    static props = {
        title: String,
        buttons: { type: Array, optional: true },
        startingValue: { type: String, optional: true },
        placeholder: { type: String, optional: true },
        rows: { type: Number, optional: true },
        getPayload: Function,
        close: Function,
    };
    static defaultProps = {
        startingValue: "",
        placeholder: "",
        rows: 1,
        buttons: [],
    };

    setup() {
        this.state = useState({ inputValue: this.props.startingValue });
        this.inputRef = useRef("input");
        onMounted(this.onMounted);
    }
    onMounted() {
        this.inputRef.el.focus();
        this.inputRef.el.select();
    }
    confirm() {
        this.props.getPayload(this.state.inputValue);
        this.props.close();
    }

    close() {
        this.props.close();
    }

    buttonClick(button) {
        console.log('Button click');
        const lines = this.state.inputValue.split("\n").filter((line) => line !== "");
        if (lines.includes(button.label)) {
            this.state.inputValue = lines.filter((line) => line !== button.label).join("\n");
            button.isSelected = false;
        } else {
            this.state.inputValue = lines.join("\n");
            this.state.inputValue += (lines.length > 0 ? "\n" : "") + button.label;
            button.isSelected = true;
        }
    }

    onKeydown(ev) {
        if (this.props.rows === 1 && ev.key.toUpperCase() === "ENTER") {
            this.confirm();
        }
    }
}


    
Finally Add the reference in __manifest__.py
add the file reference in manifest file to load the assets in pos:

{
    'name': 'POS Custom',
    'version': '1.0.0',
    'category': 'Point of Sale',
    'summary': "POS Custom, Odoo18, "
               "Odoo Apps",
    'description': "Design for better styles",
    'author': 'Zahid Anwar',
    'company': 'zalino',
    'maintainer': 'Nil',
    'website': 'https://www.zalinotech.com',
    'depends': ['base', 'point_of_sale'],
    'assets': {
        'point_of_sale._assets_pos': [
            'pos_custom/static/src/app/custom_popup/text_input_popup.js',
            'pos_custom/static/src/app/custom_popup/text_input_popup.xml',

            'pos_custom/static/src/app/custom_button/custom_button.js',
            'pos_custom/static/src/app/custom_button/custom_button.xml',
        ],
    },
    'license': 'AGPL-3',
    'installable': True,
    'auto_install': False,
    'application': False
}

    
Restart the service
Once all is done. Now restart the odoo service and upgrade the app. (if assets not loaded properly clear the cache of browser)

That’s it! You’ve added the custom buttons in point of sale!

Leave a Reply

Your email address will not be published. Required fields are marked *