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
Label
s and aTextBox
es and add them to analert
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
andRichText
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 formattableRichText
rather than a plainLabel
- 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 CheckBox
es 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 TextArea
s and Button
s 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