Input_box() and alert2()

While working on my apps, I keep incurring into two slightly annoying things:

  • I don’t like the default alert() because:
    • Pressing Enter does nothing (no default button)
    • The buttons don’t look like the other buttons in the app
    • The text is… just a plain text
  • I don’t like to create myriads of mini-forms for the simplest data inputs because:
    • I end up with inconsistent looks and behaviors
    • Too much work to take care of default button, focus, validation, etc.
    • I don’t like to manage the events required to get the input form to communicate with its parent form
  • Nor to dynamically create Labels and a TextBoxes and add them to an alert because:
    • It’s difficult to set the focus on the first TextBox
    • It’s difficult to manage the default button or the pressed_enter event

Those two things kept bothering me enough that I created an input_box() and an alert2() functions to address the problem.

Now my apps don’t have a bunch of little input forms, all the input forms look and behave consistently, all have consistent validation and all the code that manages them is inside the form that uses them instead of being spread across many little forms.

The input_box() function takes care of all those problems and a little more:

  • It allows to add rows with TextBox, TextArea, DropDown, CheckBox, Button and RichText components
  • Each input component can have a prompt
  • The buttons (at the bottom or added in the rows) use the same style as all other app buttons
  • It sets the focus on the first input component
  • It uses the Validator dependency to manage the validation of all input elements
  • It allows to create the alert2() function that uses the same style
  • The alert2() has a formattable RichText rather than a plain Label
  • It manages dynamic content

The alert2() function is a simple replacement of the native alert() function with three differences:

  • It does not accept components
  • The first argument is the content of a RichText, that is a formattable text
  • It has the default_button argument that allows to press enter to trigger the click on one button

The input_box() function allows to add a number of rows, each with either a RichText or an input component. The list of rows is specified with the items argument. The function returns a dictionary with one value per input component plus one element with the clicked button.

Large input forms can be managed with one single call to input_box(), but defining a large items can quickly become cumbersome, so it is possible to obtain the same result with something like this:

ib = InputBox(title='My title', [...])
ib.add_textbox(10, 'Width:')
ib.add_textbox(10, 'Height:')
if ib.show() != 'OK':
    return
print(ib.results['Width:'], ib.results['Height:'])

The example app below shows how to use alert2(), input_box() and InputBox.

One note about the InputBox.results dictionary: the dictionary contains an element per input component. The dictionary keys are the name argument of the row. If name is not provided, then prompt is used. If also prompt is missing, then text is used (see the CheckBoxes in the example app`).

The elegant way would be to include name for every row. The lazy way (which I always use) is to use the prompt to identify the rows. I only use name when there is no prompt (see 'name': 'notes' in the example app).

The same logic that sets the name for the items of InputBox.results is used to identify the items of InputBox.rows. The dictionary InputBox.rows and the list InputBox.rows_list allow to access InputBoxRow objects and can be used during validation (see the validating_function function in the example app) and to manage dynamic content (see the dropdown_change function in the example app).

The example app uses the almost out-of-the-box Material Design. I added a few rows at the top of theme.css that affect how TextAreas and Buttons look. They are not required for the app to work.


This is the example app:


This clone link includes the example app and the InputBox dependency. It does require but not include the Validator dependency. You can clone that from here, then replace the invalid dependency from the InputBox app with your copy of the Validator.
https://anvil.works/build#clone:LIZHS2JJBZLK2YC3=EZPVHMZ4WSJJGVLLMREMFPT4

18 Likes

thanks very much for this!!

I was experimenting with the wording to use on an alert, and I kept changing the code and rerunning the app. Tedious slow job.

Then I realized that the Beta IDE has an awesome console, so I tried this and it worked:

image

5 Likes

Hi Stefano. For this very useful addition also the humble request to package it as a 3rd party dependency with token. It would make updating much easier. TIA

BTW most buttons do not display well (on Safari):

2 Likes

@stefano.menci Is @anvil working with you to adopt and integrate this? It doesn’t seem like a lot of work to do so (you did most of the heavy-lifting), and is a delightful improvement on the stock alert.

Alerts are so crucial, foundational actually, towards guiding users in any setting, but is especially so in applications where step-by-step guidance is a killer feature believe it or not (like in Apps for children). That’s my case.

I hope @anvil does.

3 Likes