Modal Overlay Forms

Is it possible to have modal forms (with the background also disabled), a bit like the log in form?

Ah, is it something to do with https://anvil.works/doc/index.html#-div-id-alerts-alerts-div-

and custom content?

I can display a form, so I reckon this might be what I need. I’ll post an example if I get it working.

EDIT - yeah, this works. I’ll create a sample project tomorrow. Very neat.

Ok, the question has changed (but the post subject is still relevant).

from popupform import popupform
...
pf=popupform()
result=alert(title="My PopUp", content=pf, button=[('Cancel',"CANCELLED','danger')])

shows my popup form inside an alert box. All good. Questions are -

  1. on popup, the focus is still on the background form’s button (the one I clicked to show the popup - I know this because if I press the space bar a few times you end up with multiple alert boxes on top of each other). How can I shift the focus to the alert box? More specifically, how can I set a control within the popped up form to have focus. This doesn’t work inside the calling form (does nothing that I can see) -

pf.mytextbox.focus()

Same for self.mytextbox.focus() from within the popup form (though I wouldn’t expect it to as it’s displayed after the instance is created and therefore I assume after the init fuction has run). I also created a method that set the text box focus and called that after the popup instantiation and just before the alert() call, but that didn’t work either. Neither did setting it in the “show” event of the form.

  1. Is it possible to disable the background form, so that clicking away from the alert/popup doesn’t close it?

Looks like you’ve found it - the answer was indeed the alert() function.

To respond to your questions about detail:

Is it possible to disable the background form, so that clicking away from the alert/popup doesn’t close it?

Clicking the background in a pop-up will always dismiss it. However, you can loop round if the alert() returned None (which it will if you click the background). Eg:

  r = None
  while r is None:
    r = alert("Click OK", buttons=[("OK", True)])

If you actually want to hide the backing form while you display the pop-up dialog, I suppose you could navigate to a blank page temporarily (using open_form()). This is almost certainly overkill, but here’s how you’d do it:

  def button_1_click(self, **event_args):
    # Display a blank page
    open_form(ColumnPanel())
    r = None
    while r is None:
      r = confirm("Answer Yes or No; don't cancel")
    # Display this form again
    open_form(self)

This is almost certainly overkill, but I include it for completeness.


on popup, the focus is still on the background form’s button (the one I clicked to show the popup)

You’re right; this was unexpected behaviour. We’ve now changed it so that everything loses focus when you open an alert. This will go live on your apps in the next 24-48 hours.

1 Like

It was this kind of thing I was looking to emulate : https://stackoverflow.com/questions/9894339/disallow-twitter-bootstrap-modal-window-from-closing

In my experience people will click outside the box and assume the data they entered has been saved, when in actual fact it requires a positive save action followed by data validation, etc. Looping around the form would lose any data entered (unless I come up with a mechanism for saving somewhere on data change which might be overkill too).

It’s no biggie for now, just a nice to have and was curious if there was a way to do it.

Cheers.

If you keep the same content object each time you show the dialog, then UI state will be retained. Eg:

  f = PopupForm()
  while alert(f, buttons=[('OK', True)]) is None:
    pass
1 Like

Ah, yes. That would make sense, of course!