Add dynamic state to fields#
Sometimes you want to make fields read-only, invisible or required under
certain conditions.
This can be achieved using the states
attribute of the Field
.
It is a dictionary with the keys readonly
, invisible
and required
.
The values are PYSON
statements that are evaluated with
the values of the record.
In our example we make some fields read-only when the record is not in the
state opportunity
, the “End Date” required for the converted
and
lost
state and make the comment invisible if empty:
class Opportunity(...):
...
description = fields.Char(
"Description", required=True,
states={
'readonly': Eval('state') != 'draft',
})
start_date = fields.Date(
"Start Date", required=True,
states={
'readonly': Eval('state') != 'draft',
})
end_date = fields.Date(
"End Date",
states={
'readonly': Eval('state') != 'draft',
'required': Eval('state').in_(['converted', 'lost']),
})
party = fields.Many2One(
'party.party', "Party", required=True,
states={
'readonly': Eval('state') != 'draft',
})
address = fields.Many2One(
'party.address', "Address",
domain=[
('party', '=', Eval('party')),
],
states={
'readonly': Eval('state') != 'draft',
})
comment = fields.Text(
"Comment",
states={
'readonly': Eval('state') != 'draft',
'invisible': (
(Eval('state') != 'draft') & ~Eval('comment')),
})
It is also possible to set the readonly
, invisible
and icon
states
on the _buttons
.
So we can make invisible each button for the state in which the transition is
not available:
class Opportunity(ModelSQL, ModelView):
...
@classmethod
def __setup__(cls):
...
cls._buttons.update({
'convert': {
'invisible': Eval('state') != 'draft',
'depends': ['state'],
},
'lost': {
'invisible': Eval('state') != 'draft',
'depends': ['state'],
},
})
Note
The fields in Eval
statement must be added to the
depends
attribute to register the field on which the states depend.
Exercise#
As exercise we let you define the state for the button that reset to draft
state.
Let’s extend the party model.