Article Streamlit Part 4: Form Validation Part 2
Hiking Through Real-Time Validation with Streamlit
Under the clear blue skies of Austin, Texas, Rick and Chris embarked on a challenging hike through the springs and canyons, each carrying a 45-pound rucksack. Their loyal dogs trotted alongside them, tails wagging with excitement. As they navigated the winding trails, the conversation naturally shifted to their latest coding endeavors.
Rick: Adjusting his rucksack "You know, Chris, just like these trails keep us on our toes, I want my Streamlit app to keep users engaged with real-time form validation."
Chris: "Ah, stepping up your game, I see. Real-time validation can definitely enhance user experience. What's on your mind?"
Rick: "Well, in my previous app, users only found out about validation errors after submitting the form. It's like hiking all this way only to realize we forgot our snacks!"
Chris: Laughs "Can't have that! Implementing real-time validation in Streamlit is like having a trail map that updates as we walk—users get immediate feedback."
Rick: "Exactly! But I'm not entirely sure how to manage the validation state and provide that immediate feedback. Any pointers?"
Chris: "Sure thing. It's all about leveraging Streamlit's session state and reactive programming model. Think of session state as your trusty backpack—keeps everything you need within reach."
Rick: "Makes sense. And I guess real-time feedback is like our dogs alerting us to any obstacles ahead?"
Chris: "You got it! Let's dive into it when we take a break. For now, let's enjoy this hike and let the ideas flow as freely as the springs around us."
They continued their journey, the synergy between physical exertion and mental stimulation fueling their progress.
Real-Time Form Validation in Streamlit: Advanced Techniques
In this tutorial, we'll explore methods to enhance user experience by providing immediate feedback during data entry using Streamlit. By implementing real-time form validation, we can improve data quality and user satisfaction, ensuring a seamless and efficient interaction process.
Why Real-Time Validation?
Basically, as soon as you tab out of a form field, you'll get validation feedback for that field instead of waiting until you submit the entire form.
To see this article with syntax highlighting for code listings, diagrams, and images go to my website and see Article Streamlit Part 4: Form Validation Part 2.
Setting Up the Project
First, please make sure you have Streamlit installed and set up your project environment.
Create and activate a virtual environment:
# Create and activate virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\\\\Scripts\\\\activate
You can also use conda or other virtual environments. Python has many choices. I prefer using a virtual environment and usually use conda. You should use one so you don’t have package conflicts between projects.
Installing Conda:
Before creating a virtual environment with Conda, you need to install it first. Here are the commands for different operating systems:
For Ubuntu/Debian (using apt-get):
sudo apt-get update
sudo apt-get install conda
For Windows (using Chocolatey):
choco install miniconda3
For macOS (using Homebrew):
brew install --cask miniconda
Creating a Conda Virtual Environment:
Once Conda is installed, you can create and activate a virtual environment:
# Create a new environment named 'streamlit_env'
conda create --name streamlit_env python=3.12
# Activate the environment
conda activate streamlit_env
# Install Streamlit in the activated environment
pip install streamlit
After creating and activating the Conda environment, you can install Streamlit and create your application file as shown in the next steps.
Install Streamlit:
pip install streamlit
Create the application file:
touch form_validation2.py
Step-by-Step Guide to Real-Time Form Validation
1. Import Required Libraries
import streamlit as st
from datetime import datetime, date, timedelta
import re
2. Define Validation Functions
These functions validate user input and provide error messages.
2.1 Name Validation
def validate_name(name, field_name):
if not name:
return False, f"{field_name} is required"
if not re.match(r"^[a-zA-Z'\\\\s\\\\-]{2,50}$", name):
return False, f"{field_name} must contain only letters, spaces, hyphens, or apostrophes (2-50 characters)"
return True, ""
The name validation function performs the following checks:
If any of these checks fail, the function returns False along with an appropriate error message. If all checks pass, it returns True with an empty string, indicating a valid name input.
2.2 Email Validation
def validate_email(email):
if not email:
return False, "Email is required"
if not re.match(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,}$", email):
return False, "Invalid email format"
return True, ""
The email validation function performs the following checks:
If any of these checks fail, the function returns False along with an appropriate error message. If all checks pass, it returns True with an empty string, indicating a valid email input.
Here's a flow diagram describing the validation process:
graph TD
A["Start"] --> B{"Input provided?"}
B -- Yes --> C["Clean input"]
B -- No --> D["Return False, 'Input required'"]
C --> E{"Matches pattern?"}
E -- Yes --> F["Return True, ''"]
E -- No --> G["Return False, 'Invalid format'"]
D --> H["End"]
F --> H
G --> H
This diagram illustrates the general flow of the validation functions, including checking for input presence, cleaning the input (for phone numbers), pattern matching, and returning appropriate validation results.
To see this article with syntax highlighting for code listings, diagrams, and images go to my website and see Article Streamlit Part 4: Form Validation Part 2.
2.3 Phone Validation
def validate_phone(phone):
if not phone:
return False, "Phone number is required"
clean_phone = re.sub(r'[\\\\s\\\\-\\\\(\\\\)]', '', phone)
if not re.match(r'^[0-9]{10}$', clean_phone):
return False, "Phone must be 10 digits"
return True, ""
Similar to the email and phone validation but the regex matches a standard phone number.
2.4 Age Validation
def validate_age(age):
if age <= 0:
return False, "Age must be greater than 0"
if age > 120:
return False, "Age must be less than 120"
return True, ""
This validation is simpler, only checking a range. Note that there are no built-in validators per se. It's just plain Python code, which is a good thing if you're a minimalist who wants to get stuff done efficiently.
2.5 Date Validation
def validate_date(check_date):
if not check_date:
return False, "Date is required"
if check_date > date.today():
return False, "Date cannot be in the future"
return True, ""
Once again, this is just simple, easy-to-understand Python code. No special frameworks needed.
3. Initialize Session State
if 'form_submitted' not in st.session_state:
st.session_state.form_submitted = False
if 'validation_messages' not in st.session_state:
st.session_state.validation_messages = []
The above code initializes the session state. Streamlit apps rely heavily on session state management to control app logic. This pattern of checking if a value is already in the state and initializing it if not is fairly standard in a Streamlit app. Once again, it's pretty easy to understand and follow Python code. Nothing fancy here. If you've worked with other UI frameworks, where fanciness is the rule with all sorts of callbacks and such, you'll find this refreshing. This is just normal-looking Python code.
4. Create the Form Layout
form_col, validation_col = st.columns([2, 1])
with form_col:
st.header("?? Personal Information")
# ... (form fields go here)
The st.columns() function in Streamlit is used to create a horizontal layout with multiple columns. Here's a breakdown of how it works:
In the context of our form validation app, using st.columns() allows us to separate the form inputs from the validation summary, creating a more organized and user-friendly interface.
This code is creating a layout for the form section of the Streamlit app. Here's what it's doing:
This structure helps organize the app's layout, putting the form fields under a clear heading within a specific column. It improves readability and user experience by clearly separating the form section from other parts of the app.
5. Implement Real-Time Validation
For each input field, we perform validation as the user types.
5.1 First Name Field
first_name = st.text_input("First Name", key="first_name")
if first_name:
is_valid, message = validate_name(first_name, "First name")
st.session_state.first_name_valid = is_valid
if not is_valid:
st.error(message)
else:
st.success("Valid first name!")
else:
st.session_state.first_name_valid = False
Here we use st.text_input to create an input field for First Name. The key parameter is how we refer to it later. We extract the first_name from the text input field. If it's missing, we mark the first_name field as invalid by storing first_name_valid in the session as false: st.session_state.first_name_valid = False. If the first name is present, we use validate_name(...) to validate it. We get the returned message and update the session state first_name_valid. If it's not valid, we take the message we got from the validate_name function and display it with st.error. Once again, this is straightforward Python code that's easy to understand and modify without having to learn a complex framework.
Here's a Mermaid flow diagram describing the process of real-time validation for form fields:
graph TD
A[User enters data] --> B{Is field empty?}
B -- Yes --> C[Mark field as invalid]
B -- No --> D[Validate input]
D --> E{Is input valid?}
E -- Yes --> F[Mark field as valid]
E -- No --> G[Display error message]
F --> H[Display success message]
G --> I[Update session state]
H --> I
I --> J[Update validation summary]
J --> K[User continues to next field]
K --> A
To see this article with syntax highlighting for code listings, diagrams, and images go to my website and see Article Streamlit Part 4: Form Validation Part 2.
This diagram illustrates the flow of real-time validation for each form field:
5.2 Repeat for Other Fields
The other field logic looks a lot like the above. They just call the right corresponding validate method.
The code for Last Name, Phone, Age, Birth Date all pretty much follow the same pattern as First Name.
6. Check Overall Validation Status
def get_validation_status():
validation_messages = []
# Example for first name
if not st.session_state.get('first_name_valid', False):
if st.session_state.get('first_name', ''):
is_valid, message = validate_name(st.session_state.first_name, "First name")
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("First name is required")
# Repeat for other fields...
return validation_messages
The get_validation_status method collects all of the validation messages so we can display them all at once. We display validation message by the field and also all at once.
Here's a Mermaid flow diagram describing the process of form submission and validation:
graph TD
A[User clicks Submit button] --> B{Get validation status}
B --> C{Any validation messages?}
C -- No --> D[Display success message]
D --> E[Set form_submitted to True]
C -- Yes --> F[Display error message]
F --> G[List validation errors]
G --> H[User corrects errors]
H --> A
To see this article with syntax highlighting for code listings, diagrams, and images go to my website and see Article Streamlit Part 4: Form Validation Part 2.
This diagram illustrates the flow of the form submission process:
This process ensures that the form is only successfully submitted when all fields pass validation, providing clear feedback to the user about any issues that need to be addressed.
Thus, get_validation_status method gets called when the form is submitted.
if st.button("Submit"):
# Get validation messages
validation_messages = get_validation_status() ## <---
if not validation_messages:
st.success("Form submitted successfully!")
st.session_state.form_submitted = True
else:
st.error("Please fix the following validation errors:")
for message in validation_messages:
st.error(f"? {message}")
This code snippet handles form submission and validation. Here's a breakdown of its functionality:
This code ensures form submission only happens when all fields are valid, providing clear feedback to users about any errors that need correction before submission.
7. Display Validation Summary
with validation_col:
st.header("Validation Summary")
all_valid = not get_validation_status()
if all_valid:
st.success("All fields are valid! ?")
else:
messages = get_validation_status()
st.error("Fields needing attention:")
for message in messages:
st.warning(f"? {message}")
I added some helpful sidebars just for the tutorial so it aids in the display, and getting a feel for the error messages.
Here's a Mermaid flow diagram describing the process of updating the sidebar with form data:
graph TD
A[Start update_sidebar_table function] --> B[Set sidebar title to 'Form Data']
B --> C[Create dictionary of current form data]
C --> D[Initialize table header]
D --> E[Initialize empty table rows]
E --> F[Loop through each field in current_data]
F --> G[Get field value from session state]
G --> H[Determine field validation status]
H --> I[Format table row with field, value, and status]
I --> J{More fields?}
J -- Yes --> F
J -- No --> K[Combine header and rows into complete table]
K --> L[Display table in sidebar using markdown]
L --> M[Create 'Clear Form' button in sidebar]
M --> N{Clear Form clicked?}
N -- Yes --> O[Clear all session state keys]
O --> P[Rerun the app]
N -- No --> Q[End update_sidebar_table function]
This diagram illustrates the step-by-step process of updating the sidebar with the current form data and validation status:
This flow demonstrates how the sidebar is dynamically updated to reflect the current state of the form, providing real-time feedback to the user.
8. Update Sidebar with Form Data
def update_sidebar_table():
st.sidebar.title("?? Form Data")
current_data = {
'First Name': st.session_state.get('first_name', ''),
'Last Name': st.session_state.get('last_name', ''),
'Email': st.session_state.get('email', ''),
# ... other fields ...
}
table_header = "| Field | Value | Status |\\\\n|--------|--------|--------|\\\\n"
table_rows = ""
for field, value in current_data.items():
# Format value and determine status
field_key = field.lower().replace(' ', '_')
is_valid = st.session_state.get(f'{field_key}_valid', False)
status = "?" if is_valid and value else "?" if value else "?"
table_rows += f"| {field} | {value} | {status} |\\\\n"
st.sidebar.markdown(table_header + table_rows)
if st.sidebar.button("Clear Form"):
for key in st.session_state.keys():
del st.session_state[key]
st.rerun()
I created this for debugging and to show for form status for debugging and understanding the code.
9. Handle Form Submission
if st.button("Submit"):
validation_messages = get_validation_status()
if not validation_messages:
st.success("Form submitted successfully!")
st.session_state.form_submitted = True
else:
st.error("Please fix the following validation errors:")
for message in validation_messages:
st.error(f"? {message}")
We described this before, but here it is again for completeness.
Writing complex inter dependent form validation
The tricky part sometimes is when the validation depends on how some form fields relate to others. Well, this is no real problem for Streamlit. As always, it's just plain, easy-to-read Python.
def get_validation_status():
"""Get detailed validation status for all fields"""
validation_messages = []
# Check each field and collect validation messages
if not st.session_state.get('first_name_valid', False):
if st.session_state.get('first_name', ''):
is_valid, message = validate_name(st.session_state.first_name, "First name")
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("First name is required")
.... # other fields
if not st.session_state.get('birth_date_valid', False):
if st.session_state.get('birth_date'):
is_valid, message = validate_date(st.session_state.birth_date)
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("Birth date is required")
# Check date range
start_date = st.session_state.get('start_date')
end_date = st.session_state.get('end_date')
if start_date and end_date and start_date >= end_date:
validation_messages.append("Start date must be before end date")
return validation_messages
Here's a Mermaid flow diagram describing the date range validation process:
graph TD
A[Start get_validation_status] --> B{Check start_date and end_date}
B --> |Both dates present| C{Is start_date >= end_date?}
C --> |Yes| D[Add error message to validation_messages]
C --> |No| E[No action needed]
B --> |One or both dates missing| E
D --> F[Return validation_messages]
E --> F
This diagram illustrates the flow of the date range validation:
The validation for the start_date and end_date fields demonstrates how Streamlit allows for straightforward implementation of complex, interdependent form validations using plain Python code. Let's break down how this works:
# Check date range
start_date = st.session_state.get('start_date')
end_date = st.session_state.get('end_date')
if start_date and end_date and start_date >= end_date:
validation_messages.append("Start date must be before end date")
This code snippet shows several key aspects of Streamlit's form validation capabilities:
This approach showcases how Streamlit leverages Python's simplicity and readability to handle complex form validations. Developers can easily understand and modify this code without needing to learn a complex framework or special syntax. The validation logic is expressed in plain Python, making it accessible and maintainable.
Now, let's take a closer look at how we implement the date range validation in our Streamlit form. This code snippet demonstrates the real-time validation of the start and end dates:
with col3:
start_date = st.date_input("Start Date", key="start_date")
with col4:
end_date = st.date_input("End Date", key="end_date")
if start_date and end_date:
if start_date >= end_date:
st.error("Start date must be before end date")
st.session_state.start_date_valid = False
st.session_state.end_date_valid = False
else:
st.success("Valid date range!")
st.session_state.start_date_valid = True
st.session_state.end_date_valid = True
The above demonstrates how to implement real-time validation the date range inputs in a and show the error messages next to the date form fields. Here's a breakdown of what it does:
Full Code Listing
Here's the complete code for the real-time form validation application.
import streamlit as st
from datetime import datetime, date, timedelta
import re
def validate_name(name, field_name):
if not name:
return False, f"{field_name} is required"
if not re.match(r"^[a-zA-Z'\\s\\-]{2,50}$", name):
return False, f"{field_name} must contain only letters, spaces, hyphens, or apostrophes (2-50 characters)"
return True, ""
def validate_email(email):
if not email:
return False, "Email is required"
if not re.match(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email):
return False, "Invalid email format"
return True, ""
def validate_phone(phone):
if not phone:
return False, "Phone number is required"
clean_phone = re.sub(r'[\\s\\-\\(\\)]', '', phone)
if not re.match(r'^[0-9]{10}$', clean_phone):
return False, "Phone must be 10 digits"
return True, ""
def validate_age(age):
if age <= 0:
return False, "Age must be greater than 0"
if age > 120:
return False, "Age must be less than 120"
return True, ""
def validate_date(check_date):
if not check_date:
return False, "Date is required"
if check_date > date.today():
return False, "Date cannot be in the future"
return True, ""
def get_validation_status():
"""Get detailed validation status for all fields"""
validation_messages = []
# Check each field and collect validation messages
if not st.session_state.get('first_name_valid', False):
if st.session_state.get('first_name', ''):
is_valid, message = validate_name(st.session_state.first_name, "First name")
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("First name is required")
if not st.session_state.get('last_name_valid', False):
if st.session_state.get('last_name', ''):
is_valid, message = validate_name(st.session_state.last_name, "Last name")
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("Last name is required")
if not st.session_state.get('email_valid', False):
if st.session_state.get('email', ''):
is_valid, message = validate_email(st.session_state.email)
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("Email is required")
if not st.session_state.get('phone_valid', False):
if st.session_state.get('phone', ''):
is_valid, message = validate_phone(st.session_state.phone)
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("Phone number is required")
if not st.session_state.get('age_valid', False):
if st.session_state.get('age', 0) > 0:
is_valid, message = validate_age(st.session_state.age)
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("Age is required")
if not st.session_state.get('birth_date_valid', False):
if st.session_state.get('birth_date'):
is_valid, message = validate_date(st.session_state.birth_date)
if not is_valid:
validation_messages.append(message)
else:
validation_messages.append("Birth date is required")
# Check date range
start_date = st.session_state.get('start_date')
end_date = st.session_state.get('end_date')
if start_date and end_date and start_date >= end_date:
validation_messages.append("Start date must be before end date")
return validation_messages
def update_sidebar_table():
st.sidebar.title("?? Form Data")
# Get current values from session state
current_data = {
'First Name': st.session_state.get('first_name', ''),
'Last Name': st.session_state.get('last_name', ''),
'Email': st.session_state.get('email', ''),
'Phone': st.session_state.get('phone', ''),
'Age': st.session_state.get('age', 0),
'Birth Date': st.session_state.get('birth_date', date.today()),
'Start Date': st.session_state.get('start_date', date.today()),
'End Date': st.session_state.get('end_date', date.today())
}
# Create markdown table
table_header = "| Field | Value | Status |\\n|--------|--------|--------|\\n"
table_rows = ""
for field, value in current_data.items():
# Format value based on type
if isinstance(value, date):
formatted_value = value.strftime('%Y-%m-%d')
elif isinstance(value, (int, float)):
formatted_value = str(value) if value != 0 else ''
else:
formatted_value = str(value)
# Determine validation status
field_key = field.lower().replace(' ', '_')
if field in ['Start Date', 'End Date']:
start_date = st.session_state.get('start_date')
end_date = st.session_state.get('end_date')
is_valid = start_date and end_date and start_date < end_date
else:
is_valid = st.session_state.get(f'{field_key}_valid', False)
# Add status emoji
status = "?" if is_valid and formatted_value else "?" if formatted_value else "?"
table_rows += f"| {field} | {formatted_value} | {status} |\\n"
st.sidebar.markdown(table_header + table_rows)
if st.session_state.get('form_submitted', False):
st.sidebar.success("Form submitted successfully!")
if st.sidebar.button("Clear Form"):
for key in st.session_state.keys():
del st.session_state[key]
st.rerun()
def main():
st.set_page_config(
page_title="Real-time Form Validation",
page_icon="?",
layout="wide"
)
st.title("? Real-time Form Validation")
# Initialize session state
if 'form_submitted' not in st.session_state:
st.session_state.form_submitted = False
# Initialize validation summary
if 'validation_messages' not in st.session_state:
st.session_state.validation_messages = []
# Create columns for the form and validation messages
form_col, validation_col = st.columns([2, 1])
with form_col:
# Personal Information
st.header("?? Personal Information")
# First Name (with real-time validation)
first_name = st.text_input("First Name", key="first_name")
if first_name: # Only validate if there's input
is_valid, message = validate_name(first_name, "First name")
st.session_state.first_name_valid = is_valid
if not is_valid:
st.error(message)
else:
st.success("Valid first name!")
else:
st.session_state.first_name_valid = False
# Last Name
last_name = st.text_input("Last Name", key="last_name")
if last_name:
is_valid, message = validate_name(last_name, "Last name")
st.session_state.last_name_valid = is_valid
if not is_valid:
st.error(message)
else:
st.success("Valid last name!")
else:
st.session_state.last_name_valid = False
# Contact Information
st.header("?? Contact Information")
# Email
email = st.text_input("Email", key="email")
if email:
is_valid, message = validate_email(email)
st.session_state.email_valid = is_valid
if not is_valid:
st.error(message)
else:
st.success("Valid email!")
else:
st.session_state.email_valid = False
# Phone
phone = st.text_input("Phone", help="Format: (123) 456-7890 or 123-456-7890", key="phone")
if phone:
is_valid, message = validate_phone(phone)
st.session_state.phone_valid = is_valid
if not is_valid:
st.error(message)
else:
st.success("Valid phone number!")
else:
st.session_state.phone_valid = False
# Personal Details
st.header("?? Personal Details")
col1, col2 = st.columns(2)
with col1:
age = st.number_input("Age", min_value=0, max_value=120, key="age")
if age > 0:
is_valid, message = validate_age(age)
st.session_state.age_valid = is_valid
if not is_valid:
st.error(message)
else:
st.success("Valid age!")
else:
st.session_state.age_valid = False
with col2:
birth_date = st.date_input("Birth Date", key="birth_date")
if birth_date:
is_valid, message = validate_date(birth_date)
st.session_state.birth_date_valid = is_valid
if not is_valid:
st.error(message)
else:
st.success("Valid birth date!")
else:
st.session_state.birth_date_valid = False
# Schedule
st.header("?? Schedule")
col3, col4 = st.columns(2)
with col3:
start_date = st.date_input("Start Date", key="start_date")
with col4:
end_date = st.date_input("End Date", key="end_date")
if start_date and end_date:
if start_date >= end_date:
st.error("Start date must be before end date")
st.session_state.start_date_valid = False
st.session_state.end_date_valid = False
else:
st.success("Valid date range!")
st.session_state.start_date_valid = True
st.session_state.end_date_valid = True
# Submit button
if st.button("Submit"):
# Get validation messages
validation_messages = get_validation_status()
if not validation_messages:
st.success("Form submitted successfully!")
st.session_state.form_submitted = True
else:
st.error("Please fix the following validation errors:")
for message in validation_messages:
st.error(f"? {message}")
# Update sidebar with current form data
update_sidebar_table()
# Display validation summary in the validation column
with validation_col:
st.header("Validation Summary")
all_valid = not get_validation_status()
if all_valid:
st.success("All fields are valid! ?")
else:
messages = get_validation_status()
st.error("Fields needing attention:")
for message in messages:
st.warning(f"? {message}")
if __name__ == "__main__":
main()
You can find this code listing at this github repo.
Running the Application
To run the application, use the following command:
streamlit run form_validation2.py
Open the provided local URL in your web browser to interact with the app.
Key Takeaways
Rick and Chris paused on a ridge overlooking a serene canyon.
Rick: "Thanks, Chris. With real-time validation, my app will be as smooth as this trail."
Chris: Smiles "Happy to help. Just remember, whether it's hiking or coding, it's all about the journey and the little adjustments along the way."
Rick: "Well said. Now, how about we let the dogs lead the way back?"
Chris: "Sounds like a plan. Maybe they'll find a shortcut!"
They laughed, resuming their hike with a renewed sense of accomplishment and the satisfaction of a day well spent.
Glossary
Term/Concept Definition Related Streamlit Component Usage Example Real-time Form Validation Immediate feedback on user input as it's entered st.text_input, st.number_input, st.date_input Validating email format as user types Session State Mechanism to store and persist data across reruns st.session_state Storing validation status of form fields Validation Functions Custom functions to check input validity N/A (Python functions) validate_email(), validate_phone() UI Feedback Visual cues for input status st.success(), st.error() Displaying green checkmark for valid input Form Layout Arrangement of input fields in the app st.columns() Creating two-column layout for related fields Sidebar Table Dynamic display of form data st.sidebar.markdown() Showing current form state in sidebar Validation Summary Overview of all validation errors st.error() Listing all invalid fields at form submission
To see this article with syntax highlighting for code listings, diagrams, and images go to my website and see Article Streamlit Part 4: Form Validation Part 2. Also, this glossary table renders correctly there.
Related Links
About the Author
Rick Hightower is a seasoned software engineer and technology enthusiast with a passion for exploring cutting-edge tools in data science and web development. With years of experience in the tech industry, Rick enjoys simplifying complex processes and making technology accessible to developers of all skill levels.
An advocate for continuous learning, Rick shares his knowledge through articles and tutorials, helping others navigate the ever-evolving landscape of software development. His exploration of real-time form validation in Streamlit demonstrates his commitment to empowering developers to create robust and user-friendly applications.
When not coding or writing, Rick can be found hiking the trails of Austin with his dog, blending his love for nature with technology, or engaging in thought-provoking conversations about the future of tech with fellow enthusiasts.
Happy coding with Streamlit! If you have any questions or need more help, feel free to explore the official Streamlit documentation or reach out to the community.