Hide time widget of datetime field according to another field value in view

Hi Trytoneers,

I’m struggling to hide the time widget of my datetime field according to the value of a seletion field.

<field name="start_period"/>
<field name="start_at" widget="date"/>
<field name="start_at" widget="time"/> <!-- I want to hide this field when start_period is not null. -->

Firstly, the view_attributes method seems to be not appropriate to change the ‘states’ attribute of a field with a PYSON (I see no example of this in Tryton’s existing modules and this not works in my tests).

@classmethod
def view_attributes(cls):
    view_attributes = super().view_attributes()
    view_attributes += [
        ('//field[@name="start_at"]', 'states', {
            'invisible': Bool(Eval('start_period')),
        })]  # This do not work.
    return view_attributes

Secondly, I don’t know how to target the time widget from the XML expression given in the view_attributes method, it seems imposible.

@classmethod
def view_attributes(cls):
    view_attributes = super().view_attributes()
    view_attributes += [
        ('//field[@name="start_at"]', 'states', {  # How to target the time widget field here?
            'invisible': Bool(Eval('start_period')),
        })]
    return view_attributes

So I tried to deal with editable function fields to separate the date and the time of my datetime field to be able to put PYSON states directly in the field declarations, instead of in view_attributes method, but this become complicate to maintain using on_change to update the “true” datetime field. So I think I’ll give up this way.

I don’t plan to replace my datetime field by two date and time fields in my DB.

Thank for help!

If I understand correctly, you want to hide the time portion of the start_at field?

What you can do is to create two Function fields both with a getter and setter. Those fields will take their portion from the start_at field and when changed update the start_at field accordingly. You display the Function fields in the XML and because the fields are separate, you can use the states attribute on the fields definition in the code to show or hide the field.

Hi @stbenus I suppose you can use tree_invisible attribute.

You can check an sample here:
https://hg.tryton.org/modules/account/file/6.4/account.py#l355

But why would you do that? Having a partial display of a field make it unusable.

@edbo Yes, I thinked about that, this is what I tried to explain when I said:

So I tried to deal with editable function fields to separate the date and the time of my datetime field to be able to put PYSON states directly in the field declarations, instead of in view_attributes method, but this become complicate to maintain using on_change to update the “true” datetime field. So I think I’ll give up this way.

But, this becames too “heavy” for the need that encounter.

@dabada83 Seems me only usable in tree views, no? In my case this is for a form. Maybe I can use 'invisible': If(Bool(Eval('start_at')), 1, 0) in the same way. But I still need a trick to “pick” the time widget in the view through the XML path.

@ced I’m storing Events bounded by two datetimes. But in some cases, the time part is described by the given “period”. When it’s the case, I define the time of the datetime to 00:00:00. Just want to hide this part to do not disturb the users especially because when the timezone of the navigator applies, the time part is “misplaced”.

You don’t need an on_change function, just one getter and one setter function. Both Function fields can call the same getter and setter. Both the getter and setter are getting the name of the field so you can check on that one. As far as I know this is the only way to achieve what you want in an easy way. Maybe it’s more code but it’s more readable and give you more flexibility in the future.

I’m using the same pattern (multiple Function fields with one getter) in several modules and it just works. The only difference with yours is that you want to update a portion of a field with two Function fields.

If you need sometimes to store a datetime and other times a date, you need to use two fields. It is cleaner and less error prone. Also a datetime is in UTC so you can not rely on the 00:00:00 time because it is not always that.

Yes, I also think that separating the time and date parts would be better. But I would have expected that quickly hide the time widget in the view works, it almost seems to work that way. I work for a minor version, I would have liked to avoid a migration of data.

So, thank to all, may be I will return with a piece of code soon, probably integrating the solution of @edbo too, but also maybe spliting the field.