Add dynamic state to fields

Contents

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.