if i understand your description, you have 2 independent forms on the same page that both send POST
requests to the same view function to process.
you want to update the placeholder below of each form depending on which form is already submitted, here i think you need to perform an ajax
call since (based on your code above) there's no way to keep or persist the data of the other form (database for e.g)
so to do:
- update the code of the Form
InputForm
since the 2 forms have the same fields you need just one for this use case and then adapt and extend the logic for other forms with different set of fields
from flask_wtf import FlaskForm
from wtforms.fields import FloatField, SubmitField
from wtforms.validators import DataRequired
class InputForm(FlaskForm):
r = FloatField('r', validators=[DataRequired()])
t = FloatField('t', validators=[DataRequired()])
u = FloatField('u', validators=[DataRequired()])
submit = SubmitField('Submit')
<!-- the first form -->
<form class="form" id="form-1" method="POST" novalidate>
{{ form_1.csrf_token }}
<div class="row">
<div class="col">
<div class="form-group row">
<div class="col-sm-3">
{{ form_1.r.label(class="col-form-label") }} <span class="text-danger">*</span>
</div>
<div class="col-sm-9">
{{ form_1.r(class="form-control rounded-0 shadow-none", **{"placeholder":"0"}) }}
<div class="invalid-feedback"></div>
</div>
</div>
</div>
<div class="col">
<div class="form-group row">
<div class="col-sm-3">
{{ form_1.t.label(class="col-form-label") }} <span class="text-danger">*</span>
</div>
<div class="col-sm-9">
{{ form_1.t(class="form-control rounded-0 shadow-none", **{"placeholder":"0"}) }}
<div class="invalid-feedback"></div>
</div>
</div>
</div>
<div class="col">
<div class="form-group row">
<div class="col-sm-3">
{{ form_1.u.label(class="col-form-label") }} <span class="text-danger">*</span>
</div>
<div class="col-sm-9">
{{ form_1.u(class="form-control rounded-0 shadow-none", **{"placeholder":"0"}) }}
<div class="invalid-feedback"></div>
</div>
</div>
</div>
</div>
<div class="form-group row d-flex justify-content-between border bg-light p-3">
{{ form_1.submit(class="btn btn-sm btn-primary rounded-0 shadow-none") }}
<span class="placeholder">sin(r) * t + u = 0.00</span>
</div>
</form>
<!-- the second form -->
<form class="form" id="form-2" method="POST" novalidate>
{{ form_2.csrf_token }}
<div class="row">
<div class="col">
<div class="form-group row">
<div class="col-sm-3">
{{ form_2.r.label(class="col-form-label") }} <span class="text-danger">*</span>
</div>
<div class="col-sm-9">
{{ form_2.r(class="form-control rounded-0 shadow-none", **{"placeholder":"0"}) }}
<div class="invalid-feedback"></div>
</div>
</div>
</div>
<div class="col">
<div class="form-group row">
<div class="col-sm-3">
{{ form_2.t.label(class="col-form-label") }} <span class="text-danger">*</span>
</div>
<div class="col-sm-9">
{{ form_2.t(class="form-control rounded-0 shadow-none", **{"placeholder":"0"}) }}
<div class="invalid-feedback"></div>
</div>
</div>
</div>
<div class="col">
<div class="form-group row">
<div class="col-sm-3">
{{ form_2.u.label(class="col-form-label") }} <span class="text-danger">*</span>
</div>
<div class="col-sm-9">
{{ form_2.u(class="form-control rounded-0 shadow-none", **{"placeholder":"0"}) }}
<div class="invalid-feedback"></div>
</div>
</div>
</div>
</div>
<div class="form-group row d-flex justify-content-between border bg-light p-3">
{{ form_2.submit(class="btn btn-sm btn-primary rounded-0 shadow-none") }}
<span class="placeholder">sin(r) * t + u = 0.00</span>
</div>
</form>
in your view function (here i just i isolated the logic in Blueprint
@bp
):
from flask import Blueprint, render_template, request, jsonify
from .forms import InputForm
from .utils import compute
bp = Blueprint(
'home',
__name__,
static_folder='static',
static_url_path='/home/static',
template_folder='templates',
# url_prefix=None,
# subdomain=None,
# url_defaults=None,
# root_path=None,
# cli_group=<object object>
)
@bp.route('/', methods=['GET', 'POST'])
def index():
form_1 = InputForm()
form_2 = InputForm()
if request.method == 'POST':
# we handle the "POST" request of the submitted "form_1"
if form_1.validate_on_submit():
r = form_1.r.data
t = form_1.t.data
u = form_1.u.data
s = compute(r,t,u)
return jsonify(s=s if s else 0, errors={})
else:
return jsonify(s=0, errors=form_1.errors)
# we handle the "POST" request of the submitted "form_2"
if form_2.validate_on_submit():
r = form_2.r.data
t = form_2.t.data
u = form_2.u.data
s = compute(r,t,u)
return jsonify(s=s if s else 0, errors={})
else:
return jsonify(errors=form_2.errors)
return render_template("home/index.html", form_1=form_1, form_2=form_2)
i suggest you my answer on how to take advantage of jinja2
template inheritance to insert locally a js
(the same with css
) blocks for particular page.
base on, i assume your are using jquery
and since we want jinja2
to render this javascript line url: "{{ url_for('home.index') }}",
so in your template
add this code
$(document).ready(function() {
"use strict";
$('.form').submit(function(e) {
e.preventDefault();
// get the id of the form currently submitted
let id = $(this).attr('id');
$.ajax({
url: "{{ url_for('home.index') }}",
type: 'POST',
cache: false,
dataType: 'json',
data: $('#' + id).serialize(), // serialize the form
success: function(data) {
// console.log(data);
// sanitize the form before processing the submitted fields
if( ! data.errors.hasOwnProperty('r')){
$('#' + id + ' input[name=r]').removeClass('is-invalid').next(".invalid-feedback").text('');
}
if( ! data.errors.hasOwnProperty('t')){
$('#' + id + ' input[name=t]').removeClass('is-invalid').next(".invalid-feedback").text('');
}
if( ! data.errors.hasOwnProperty('u')){
$('#' + id + ' input[name=u]').removeClass('is-invalid').next(".invalid-feedback").text('');
}
// @see https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
if( ! jQuery.isEmptyObject(data.errors)) { // Errors (data.errors = {})
console.log('Errors');
if(data.errors.hasOwnProperty('r')){
$('#' + id + ' input[name=r]').addClass('is-invalid').next(".invalid-feedback").text(data.errors['r']);
}
if(data.errors.hasOwnProperty('t')){
$('#' + id + ' input[name=t]').addClass('is-invalid').next(".invalid-feedback").text(data.errors['t']);
}
if(data.errors.hasOwnProperty('u')){
$('#' + id + ' input[name=u]').addClass('is-invalid').next(".invalid-feedback").text(data.errors['u']);
}
// update placeholder with the returned value
$('#' + id + ' .placeholder').html('sin(r) * t + u = ' + data.s);
} else { // Passed
console.log('Passed');
// get the submitted fields
let r = $('#' + id + ' input[name=r]').val();
let t = $('#' + id + ' input[name=t]').val();
let u = $('#' + id + ' input[name=u]').val();
// update placeholder with the returned value
$('#' + id + ' .placeholder').html('sin(' + r + ') * ' + t + ' + ' + u + ' = ' + data.s);
// reset fields
$('#' + id + ' input[name=r]').val('');
$('#' + id + ' input[name=t]').val('');
$('#' + id + ' input[name=u]').val('');
}
}
});
});
});
and finally this a 
hope this solves your issue.