Search code examples
pythonodoo

How to make Odoo form readonly when the record has an specific state?


I have an entity "payment" in Odoo that has several states. I want to open the form of a payment in readonly mode (disable edit button) when that payment has the state "paid". How do I do that?


Solution

  • The correct way is to add readonly attribute to all the fields, like this:

    <field name="my_field" attrs="{'readonly':[('state','=','paid')]}"/>
    

    but if you still want to hide the edit button, then you need to override the form controller, here's how:

    1. Create a javascript file in your module static folder: my_module/static/src/js/my_form_view.js
    2. Add this inside the my_form_view.js:
    odoo.define('my_module.MyCustomForm', function (require) {
    "use strict";
    
        var FormController = require('web.FormController');
        var viewRegistry = require('web.view_registry');
        var FormView = require('web.FormView');
    
        var MyFormController = FormController.extend({
            _updateButtons: function () {
                this._super.apply(this, arguments);
                if (this.$buttons) {
                    if (this.renderer.state.data.state !== 'paid'){
                        this.$buttons.find('.o_form_button_edit').show();
                    } else {
                        this.$buttons.find('.o_form_button_edit').hide();
                    }
                }            
            },
    
        });
    
        var MyFormView = FormView.extend({
            config: _.extend({}, FormView.prototype.config, {
                Controller: MyFormController,
            }),
        });
        viewRegistry.add('custom_form', MyFormView);
    
    });
    
    1. add your js script to asset backend, by creating a new file, my_module/views/asset.xml, and the content should be:
    <?xml version="1.0"?>
    <odoo>
    
        <template id="assets_backend" name="my_backend_assets" inherit_id="web.assets_backend">
            <xpath expr="." position="inside">
                <script type="text/javascript" src="/my_module/static/src/js/my_form_view.js" />
            </xpath>
        </template>
    
    </odoo>
    
    1. also you need to add your custom form view to the form view, like this
    <?xml version="1.0" encoding="utf-8"?>
    <odoo>
        <record id="my_model_form_view" model="ir.ui.view">
            <field name="name">my.model.form</field>
            <field name="model">my.model</field>
            <field name="arch" type="xml">
                <form js_class="custom_form">
                ... your form contents
                </form>
            </field>
        </record>
            
    </odoo>