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.