I am working on a user login using Flask and the following extensions: Flask-Login
, Flask-WTF
, WTForms
and Flask-SocketIO
Client-Side
Rendering of Forms and pre-filling with data is done with Flask-WTF
/ WTForms
just like this:
<form class="form-horizontal" role="form" id="username-password-form" method="post" action="/settings/system/userpassword">
<div class="form-group">
<label for="inputEmail3" class="col-sm-3 control-label">Username</label>
<div class="col-sm-9">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
{{ form.hidden_tag() }}
{{ form.name(size=20, class_='form-control', placeholder='Username') }}
</div>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">Password</label>
<div class="col-sm-9">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
{{ form.password(size=20, class_='form-control', placeholder='Password') }}
</div>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">Confirm Password</label>
<div class="col-sm-9">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
{{ form.password_confirm(size=20, class_='form-control', placeholder='Retype Password') }}
</div>
</div>
</div>
</form>
Server-Side (Python)
In Python the responsible code for handling the Form is encapsulated in a Flask-Blueprint:
class UsernamePasswordForm(Form):
name = StringField('name', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired()])
password_confirm = PasswordField('password_confirm', validators=[DataRequired()])
def validate_on_submit(self):
rv = Form.validate_on_submit(self)
if not rv:
return False
# Validation not yet implemented ...
return True
blueprint = Blueprint('settings_system', __name__)
@blueprint.route('/')
def settings_system():
return render_template('settings-system.html')
@blueprint.route('/userpassword', methods=('GET', 'POST'))
def set_username_password():
form = UsernamePasswordForm()
if form.validate_on_submit():
socket_io.emit('user_password_successfull', namespace='/test')
return ('', 204)
form.name.data = 'Current Name'
return render_template('settings-system-username-password-modal.html', form=form)
Socket-IO
My intention was to give feedback right after the user has submitted the form back to the server. So instead of just responding with rendering of a template, I returned an empty response:
return ('', 204)
To feedback results to the browser / client I am using Flask-SocketIO
. Just before returning an empty response, Socket-IO emits a message that the Form was validated.
socket_io.emit('user_password_successfull', namespace='/test')
On the Client side I am using this Socket-IO
message to - for example - close a modal or let the user know that he has successfully entered the user information.
In case of wrong input or something went wrong during form validation I can emit a Socket-IO
message which - for example - shows an error message or changes the HTML
using jQuery
so that the user directly knows which form-field was forcing that error, etc. For Exempel:
socket.on('user_password_successfull', function () {
$( '#username-password-modal' ).modal('hide');
swal("Good job!", "done", "success")
});
Since these are still my first steps on Web-Applications, jQuery
, Socket-IO
, etc. I am really looking forward to get some feedback on my concept of handling real-time form validation feedback to the user.
Also let me know if there is something wrong with using classic Forms with Socket-IO
realtime feedback on top!?