I made a simple form in Flask using Flask-WTForms where a parent can register itself and his children. The parent can register as many children as he wants, by clicking on the button 'Add child'. WTForms makes this pretty easy to implement by using the FieldList feature.
However, after clicking on the button 'Add child' the page refreshes itself because it makes a request to the server. I want to use an AJAX request to add a child form, so the page doesn't refreshes itself.
I know how to do an AJAX-request, send a response back and add this response to the html page. However, I do not know how to append an entry to the form object and return the page itself (somehow) with the updated form-object. Is that even possible?
My forms:
class ChildForm(FlaskForm):
name = StringField(label='Name child')
age = IntegerField(label='Age child')
class Meta:
# No need for csrf token in this child form
csrf = False
class ParentForm(FlaskForm):
name = StringField(label='Name parent')
children = FieldList(FormField(ChildForm), label='Children')
add_child = SubmitField(label='Add child')
submit = SubmitField()
My routes:
@app.route('/register', methods=['GET', 'POST'])
def register():
form = ParentForm()
if form.add_child.data:
form.children.append_entry()
return render_template('register.html', form=form)
if form.validate_on_submit():
# do something with data
return render_template('register.html', form=form)
register.html:
<form action="{{ url_for('register') }}" method="post" id="parentForm">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name }}
{{ form.add_child }}
{% for childform in form.children %}
{% for field in childform %}
{{ field.label }} {{ field }}
{% endfor %}
{% endfor %}
{{ form.submit }}
</form>
I think this should work. Barring any typos.
views.py
########
# SET UP YOUR FLASK APP HERE
########
from flask_wtf import FlaskForm
from wtforms_alchemy import model_form_factory
class Family(db.Model):
id = db.Column('id', db.Integer, primary_key=True)
name = db.Column(db.String(500), info={'label': 'Familyname', 'validators': DataRequired()})
class Member(db.Model):
id = db.Column('id', db.Integer, primary_key=True)
name = db.Column(db.String(500), info={'label': 'Member', 'validators': DataRequired()})
BaseModelForm = model_form_factory(FlaskForm)
class ModelForm(BaseModelForm):
@classmethod
def get_session(self):
return db.session
class MemberForm(ModelForm):
class Meta:
model = Machine
class MemberEditForm(MemberForm):
pass
class MainForm(ModelForm):
add_member = SubmitField('+ Member')
members = ModelFieldList(FormField(MemberForm))
class Meta:
model = Family
@app.route('/form')
def main_form():
family = Family()
form = MainForm(obj=family)
if form.add_member.data:
getattr(form,'members').append_entry()
return render_template('form.html', form=form)
if form.validate_on_submit():
form.populate_obj(family)
db.session.add(order)
db.session.commit()
return render_template('form.html', form=form)
@app.route('/process_add_member', methods=['POST'])
def add_member():
form = MainForm()
getattr(form,'members').append_entry()
return render_template('members.html', form=form)
form.html
<script type="text/javascript">
$("#add-member").on('click', function(event){
$.ajax({
url: "{{ url_for('add_member') }}",
type : "POST",
//dataType : 'json', // data type
data : $("#main-form").serialize(),
success : function(result) {
console.log(result);
$("#members").html(result);
},
error: function(xhr, resp, text) {
console.log(xhr, resp, text);
}
});
event.preventDefault();
});
</script>
<form method="post" action="{{ url_for('main_form') }}" id="main-form">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name }}
<fieldset class="form-group border p-2">
<span id="members">{% include 'members.html' %}</span>
<div class="form-row">
{{ form.add_member(id="add-member") }}
</div>
</fieldset>
</form>
members.html
<span class="h3">Members</span>
{% if form.members%}
<div class="form-row">
<div class="col-1 form-group">Name</div>
</div>
{% endif %}
{% for member in form.members %}
<div class="form-row">
{% for field in member %}
<div class="col-1 form-group">{{ field(class="form-control") }}</div>
{% endfor %}
</div>
{% endfor %}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With