Anvil Community Forum

Add query_close event

When a form is replaced by another form, either by the get_open_form().content_panel.clear(), by the open_form() or by whatever other technique is available in Anvil to close a form, the query_close() event should be fired on the form that is disappearing.

This allows to wrap things up and, for example, ask the user whether to save the content of the form, and allow the user to cancel the form closing.

In the good old VB6 the FormUnload event had the Cancel argument that could be set to True to prevent the form from closing.

I don’t know what the best way would be to achieve the same result in Anvil.

Perhaps the event should raise an exception, which would prevent the get_open_form().content_panel.clear() or the open_form() from doing their job.

Or perhaps the event should just return True or False and the event code would look like this:

def form_query_close(self, **event_args):
  button = alert('Do you want to save your stuff?',
                 buttons=[
                   ("Yes", "Yes", "danger"),
                   ("No", "No", "info"),
                   ("Cancel", "Cancel", "default")
                 ])

  if button == 'Cancel':
    return True

  if button == 'Yes':
    self.save()

And the form managing code would look like this:

if get_open_form().content_panel.clear():
  return

get_open_form().content_panel.add_component(NewForm())

EDIT
Here is how I simulate the query_close event. It is not difficult, but an official event would be more elegant.

def show_form(self, form, *args, **kwargs):
  try:
    current_form = get_open_form().content_panel.get_components()[0]
    if current_form.query_close():
      return
  except:
    pass
    
  get_open_form().content_panel.clear()
  get_open_form().content_panel.add_component(form(*args, **kwargs))
1 Like

Here’s how I handle this situation in my application. Every data entry form in my app has a Save button. This button is disabled when the form first opens. Why? Because the user hasn’t changed anything yet! Once they make any change (trapped via a component’s On Change event), I enable the Save button - this lets the user know that something has changed on the form. Any attempt to leave the form by selecting a menu choice on the left side of the screen (I’m using the Material Design theme) is preceded by a check to see if the Save button is enabled. If it is, I prompt the user to ask them if they want to first save their change(s). If they do, great, I save their change(s) to the DB and then allow them to move on to the next form. If they don’t, then it’s simply on to the next form.

Make sense? In my case, I don’t feel the need for a On Close-type event for a form, but as a former Delphi and VB developer, I see your point.

Watching the Save button often works, but in same cases I don’t have the Save button and I still want to do something before the form is closed.

Also, I don’t like to look inside a form from outside.

The form knows whether there is a Save button, or something needs to be logged when the form closes, or if another form must open. Regardless of what the side bar is trying to do.

The first option in my post is raising an exception instead of returning a value.
At first I thought that this would prevent the function that is trying to close the from from opening the next form. But… the exception either crashes (not good) or can be managed and the next form would be opened anyway (worse).

So ideally the Anvil guys can think of a more robust and elegant way to cancel the form closing, rather than relying on the code to look at the returned value.

Bump.

I really miss the query_close event.
Can you please bump this one notch up on your priority list?

I would like the query_close event to be able to prevent a form from being unloaded when:

  • the user clicks on the back arrow on the browser
  • get_open_form().content_panel.clear() is called
  • the user clicks on a button on a custom component that causes any of the above.

For example I have one header_with_login custom component that I place on the header of each form. The custom component has a “user profile” and a “log out” button. I am also thinking about another custom component with some company (rather than app) wide navigation.

I want the form that is currently loaded on the content_panel to be able to cancel any attempt of unloading it without asking the user if they want to save.

In the good old VB6 there was the Cancel argument of the Form_QueryUnload event. That precious Cancel argument allowed to cancel the unloading of the form from inside the form, whatever was the reason that triggered the unloading (either a button on the form or an event triggered outside of the form, including closing the application or shutting down the machine).

In the good new Anvil I need to sprinkle the code that manages the unsaved document across all the links and buttons that could cause the loss of the data. And I need to write some Javascript to manage the back button (I have done that, but it’s a pain). And I need to write code inside each custom component that may navigate away from the current form (I have not done that, it would be too much of pain).