justpy
justpy copied to clipboard
Why trigger a page_update when an event handler is missing?
According to this comment, JustPy triggers a "page_update" event if an event handler returns None
.
But as I noticed right now, it also updates the page if there is no handler for an event: https://github.com/elimintz/justpy/blob/42275e9c6e00373f09affd7d781a278383171807/justpy/justpy.py#L341
This might happen for e.g. QSlider, which triggers "change" and "input" events. So you get page updates even though you implement a change event handler returning False
.
What is the reason behind this? Couldn't we remove the page updates in this case?
In this specific case it helps to create the QSlider with disable_input_event=True
.
This is the code I'm experimenting with. Omitting one of the event handlers causes page updates after every slider change.
import justpy as jp
def handle_change(sender, msg):
print('CHANGE', sender, msg, flush=True)
return False
def handle_input(sender, msg):
print('INPUT', sender, msg, flush=True)
return False
def input_test(request):
wp = jp.QuasarPage()
jp.QSlider(min=0, max=10, step=1, a=wp, change=handle_change, input=handle_input)
return wp
jp.justpy(input_test)
One option would be to not update page when event_handler returns None. But that would require an extra variable to signal when should the page be updated? Guess the best thing to do in current setup would be provide an event handler and return a value.
Or one can add an extra qualifier to if event_result is None:
to restrict to case only if event_function is defined.
Sure, you can avoid individual page updates by implementing a handler which returns a non-None value. But you need to be aware of every event that can be handled and add those empty handlers. That's why I was wondering why we need the current default behavior in the first place. If there is any event you didn't think about, why should JustPy send a whole page update message?
My initial thinking was to keep event handlers as simple as possible and usually you would like to update the page after an event. Since if there is no return statement, None is returned, that is the value that updates the page.
This design keeps the event handlers more concise but it does cause the problems as described above. It would be a big breaking change if we decide to go a different route at this stage.
I just don't see why Python should trigger a page update if it didn't subscribe to the JavaScript event in the first place. The information that something happened does not reach the user code, so the event should be no reason for an update.
These updates are problematic for our use cases where we interact with robots over the internet. Sending complex user interfaces again and again is pretty costly, especially for events like key presses or slider movements. That's why I was hunting such implicit updates.
When an input or change type event happens in the browser, the default is for the event to be sent to the backend even if the event does not have an event handler because otherwise the value on the server would not be in sync with the value in the browser. Anything the inherits from the Input component has the before event which takes care of that. So basically, Input components come with an event handler that the user does not specify.
Please take a look at https://github.com/elimintz/justpy/blob/master/justpy/htmlcomponents.py#L787
So in some implicit (to the user) way the information reaches the backend.
Right after the Input definition in the code there is the InputChangeOnly definition. Perhaps we need to extend this concept? Would that solve your problem?
Alternatively, we could change https://github.com/elimintz/justpy/blob/master/justpy/justpy.py#L307 so that the default would be that if there is only a before event and not a user specified handler, the page is not updated. The potential problem with this is that a user defined before event or some background task may cause side effects that do require the page to be updated.
Ok, I see. My tendency was indeed to change this line
https://github.com/elimintz/justpy/blob/42275e9c6e00373f09affd7d781a278383171807/justpy/justpy.py#L341
to = False
, i.e. treating a missing event handler as if there was one which returned False
.
I wasn't aware of the before- (and after-?) events. That might be something to consider, but I don't know the code well enough to foresee its consequences. Still, if the user didn't subscribe to any event, e.g. just places a slider on a blank page, I wouldn't expect any page updates when moving it. And I'm not sure if possible side effects should drive the default behavior.
But if I had to decide at this point in time, I would tend to leave it as it is, to avoid potentially breaking existing code. If performance is critical, one would need to know about these page updates and how to avoid them. Or use NiceGUI which takes care of those lower-level details. 😉