In Odoo 16, I'm trying to make all fields from a form view readonly depending on the value of other field of the same form.
First I've tried the following:
<xpath expr="//field" position="attributes">
<attribute name="attrs">{'readonly': [('my_field', '=', True)]}</attribute>
</xpath>
With no result.
I can't use <form edit="false">
neither since I have to check the field value.
A rule with <field name="perm_write">1</field>
works, but it doesn't behave as I need, since it allows you to modify the whole form until you click on Save and get the permission error.
And overwriting get_view
is not a valid option, since cannot depend on my_field
value.
The only solution I can find is to modify each field of the form with xpath
, which is pretty disturbing, and is not consistent if in the future more fields are added to the form view via other apps.
Does anyone have a better solution for this?
Extending get_view
actually is a good idea. There is a module in server-ux repo of the OCA where something similar is done: when something is saved in a one2many field, every field in the form view will be set to readonly. To do this, the readonly modifier is rewritten for each field.
The module: base_tier_validation
The interesting part of code: get_view
Code for your case:
@api.model
def get_view(self, view_id=None, view_type="form", **options):
res = super().get_view(
view_id=view_id,
view_type=view_type,
**options,
)
if view_type == "form":
doc = etree.XML(res["arch"])
for field in doc.xpath("//field[@name][not(ancestor::field)]"):
modifiers = json.loads(
field.attrib.get("modifiers", '{"readonly": false}')
)
if modifiers.get("readonly") is not True:
modifiers["readonly"] = OR(
[
modifiers.get(
"readonly", []
) or [],
[("my_field", "=", True)],
]
)
field.attrib["modifiers"] = json.dumps(modifiers)
res["arch"] = etree.tostring(doc, pretty_print=True)
return res