Dynamic forms enhance the user experience by updating the parts of a web page without the full page reload, the powerful library can allow for the AJAX requests and dynamic updates, while Flask can provide a robust backend framework for Python. This article will guide you through integrating the HTMX with Flask to create dynamic forms.
- HTMX: It can allow you to use the AJAX, CSS transitions, and WebSockets directly in the HTML. It can enable you to update the parts of the Web page dynamically based on the user interactions without needing to write the extensive JavaScript Code.
- Flask: It is a micro web framework for Python. It can be designed to be simple and easy to use, making it a good choice for small to medium-sized applications. Flask is based on the WSGI toolkit and Jinja2 template engine.
Setting up Flask and HTMXInstalling the FlaskWe need to install the Flask using pip:
pip install Flask Installing the HTMXHTMX is the JavaScript library that can be included via the CDN and add the following scripts to the HTML template.
<script src="https://unpkg.com/[email protected]"></script> Creating the Basic Flask ApplicationCreate the new file named as app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/') def index(): return render_template('index.html')
if __name__ == '__main__': app.run(debug=True) - Flask(__name__): It can be initializes the Flask application.
- @app.route(‘/’): It can defines the routes for the homepage and renders the index.html template.
- app.run(debug=True): It can be starts the development server with debug mode enabled.
HTMX Setup:Include the HTMX in HTMLAdd the HTMX library to the HTML via CDN
<script src="https://unpkg.com/[email protected]"></script> This script can allows you to use the HTMX features such as the AJAX requests and dynamic content updates directly into the HTML page.
Create the new directory for the project and setup the basic Flask application.
Project Structure templates/index.html
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic Forms with HTMX and Flask</title>
<script src="https://unpkg.com/[email protected]"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<h1>Dynamic Forms with HTMX and Flask</h1>
<form hx-get="/update-fields" hx-target="#dynamic-fields">
<div class="form-group">
<label for="type">Form Type:</label>
<select id="type" name="type" class="form-control">
<option value="basic">Basic</option>
<option value="advanced">Advanced</option>
</select>
</div>
</form>
<form hx-post="/submit" hx-target="#response" hx-swap="innerHTML">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name" name="name" class="form-control" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" class="form-control" required>
</div>
<div class="form-group">
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone" class="form-control">
</div>
<div class="form-group">
<label for="address">Address:</label>
<textarea id="address" name="address" class="form-control"></textarea>
</div>
<div id="dynamic-fields"></div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div id="response"></div>
</div>
</body>
</html>
static/styles.css
CSS
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.container {
width: 80%;
max-width: 800px;
margin: 20px auto;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
text-align: center;
color: #333;
}
form {
margin-bottom: 20px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"],
input[type="email"],
input[type="tel"],
textarea {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
textarea {
height: 100px;
}
button {
padding: 10px 20px;
border: none;
border-radius: 4px;
background-color: #007bff;
color: #fff;
font-size: 16px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.alert {
padding: 15px;
margin-top: 20px;
border-radius: 4px;
}
.alert-success {
background-color: #d4edda;
color: #155724;
}
.alert-error {
background-color: #f8d7da;
color: #721c24;
}
test/test_app.py
Python
import pytest
from app import app
@pytest.fixture
def client():
app.config['TESTING'] = True
with app.test_client() as client:
yield client
def test_index(client):
response = client.get('/')
assert b'Dynamic Forms with HTMX and Flask' in response.data
def test_update_fields_basic(client):
response = client.get('/update-fields', query_string={'type': 'basic'})
assert b'' in response.data
def test_update_fields_advanced(client):
response = client.get('/update-fields', query_string={'type': 'advanced'})
assert b'Additional Information' in response.data
def test_submit(client):
response = client.post('/submit', data={'name': 'Alice', 'email': '[email protected]'})
assert b'Hello, Alice!' in response.data
def test_submit_with_extra_field(client):
response = client.post('/submit', data={'name': 'Alice', 'email': '[email protected]', 'extra': 'Extra Value'})
assert b'Hello, Alice! Extra field value: Extra Value' in response.data
def test_submit_no_name(client):
response = client.post('/submit', data={'email': '[email protected]'})
assert b'Error: Name and Email are required!' in response.data
app.py
Python
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/update-fields')
def update_fields():
type_ = request.args.get('type')
if type_ == 'advanced':
fields = '''
<div class="form-group">
<label for="extra">Additional Information:</label>
<input type="text" id="extra" name="extra" class="form-control">
</div>
'''
else:
fields = ''
return fields
@app.route('/submit', methods=['POST'])
def submit():
name = request.form.get('name')
email = request.form.get('email')
phone = request.form.get('phone')
address = request.form.get('address')
extra = request.form.get('extra', '')
if not name or not email:
return "<p>Error: Name and Email are required!</p>", 400
response = f"""
<div class="alert alert-success">
<h4>Submission Successful!</h4>
<p><strong>Name:</strong> {name}</p>
<p><strong>Email:</strong> {email}</p>
<p><strong>Phone:</strong> {phone}</p>
<p><strong>Address:</strong> {address}</p>
<p><strong>Additional Info:</strong> {extra}</p>
</div>
"""
return response
if __name__ == '__main__':
app.run(debug=True)
Output
ConclusionCombining the HTMX with Flask for the powerful dynamic form handling. By the following these steps outlined above, we can create the responsive, interactive web applications that improve the user experience. Continue to explore the HTMX and Flask documentation for more advanced features and best pratices.
|