I'm struggling to change the labels for FieldList subforms added dynamically using .append_entry(). I can successfully change the labels for the overall form, and for directly in front of each individual field, but I still get a bullet and a default label-0, label-1, label-2 etc. above each successive field instance and I can't rename it or get rid of it.
I am creating a form that gathers characteristics about a varying number of communities and militants that exist in a varying number of regions. I have one overall form and four subforms. For example, if I have 2 regions and 3 communities, the first part of my form called regionpercent asks for the percent of each region's population that identifies with each community, looking something like this:
Region 1
Percent Community 1:
Percent Community 2:
Percent Community 3:
Region 2
Percent Community 1:
Percent Community 2:
Percent Community 3:
So I need to change the sublabels for regionpercent to ['Region1<br>
Percent Community 1:', 'Percent Community 2:', 'Percent Community 3:', '<br>
Region 2<br>
Percent Community 1:', 'Percent Community 2:', 'Percent Community 3:']. But right now, before each of the six fields I have a "regionpercent-0", "regionpercent-1" and so on.
The main form is called ThirdForm().
Here are my form classes:
class RegionForm2(FlaskForm):
x = FloatField(validators=[InputRequired()])
def __init__(self, labels=None, **kwargs):
super().__init__(**kwargs)
if labels is None:
labels = ['percent of the population:']
self.x.label = Label(self.x.id, labels[0])
class GrievancesForm(FlaskForm):
box = BooleanField(validators=None)
def __init__(self, labels=None, **kwargs):
super().__init__(**kwargs)
if labels is None:
labels = ['Grievance?:']
self.box.label = Label(self.box.id, labels[0])
class AffiliationsForm(FlaskForm):
boxm = BooleanField(validators=None)
def __init__(self, labels=None, **kwargs):
super().__init__(**kwargs)
if labels is None:
labels = ['Affiliation?:']
self.boxm.label = Label(self.boxm.id, labels[0])
class MilitantForm2(FlaskForm):
reg = BooleanField(validators=None)
def __init__(self, labels=None, **kwargs):
super().__init__(**kwargs)
if labels is None:
labels = ['Active?:']
self.reg.label = Label(self.reg.id, labels[0])
class ThirdForm(FlaskForm):
regionpercent = FieldList(FormField(RegionForm2))
grievances = FieldList(FormField(GrievancesForm))
affiliations = FieldList(FormField(AffiliationsForm))
milactive = FieldList(FormField(MilitantForm2))
submit = SubmitField('Submit')
def __init__(self, labels=None, **kwargs):
super().__init__(**kwargs)
if labels is None:
labels = ['Percentage of Each Community Present in Each Region', 'Grievances Between Communities', 'Affiliation of Communities with Militants', 'Active Militants in Each Region']
self['regionpercent'].label = Label(self['regionpercent'].id, labels[0])
self['grievances'].label = Label(self['grievances'].id, labels[1])
self['affiliations'].label = Label(self['affiliations'].id, labels[2])
self['milactive'].label = Label(self['milactive'].id, labels[3])
Here is my routes.py:
@app.route('/page3', methods=['GET', 'POST'])
def page3():
regionnames = session.get('regionnames', None)
communitynames = session.get('communitynames', None)
militantnames = session.get('militantnames', None)
form = ThirdForm()
if form.validate_on_submit():
regiondata = form.regionpercent.data
return redirect(url_for('next_page'))
for i in range(len(regionnames)*len(communitynames)):
form.regionpercent.append_entry()
for i in range(len(communitynames)*(len(communitynames)-1)):
form.grievances.append_entry()
for i in range(len(communitynames)*len(militantnames)):
form.affiliations.append_entry()
for i in range(len(regionnames)*len(militantnames)):
form.milactive.append_entry()
print('regionpercent:', form.regionpercent)
return render_template('page3.html', title='Third Page', form=form)
And here is my HTML:
<h1> Model Parameters- Page 3</h1>
<h3> More Properties</h3>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.regionpercent.label }}<br>
{{ form.regionpercent(size=32) }}
</p>
<p>
{{ form.grievances.label }}<br>
{{ form.grievances(size=32) }}
</p>
<p>
{{ form.affiliations.label }}<br>
{{ form.affiliations(size=32) }}
</p>
<p>
{{ form.milactive.label }}<br>
{{ form.milactive(size=32) }}
</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
Despite manually adding labels I still see <label for="regionpercent-0">Regionpercent-0</label>
if I print form.regionpercent.
I imported lists in my routes.py file of region, community, and militant names so that I could use them as the labels, but I haven't made it that far yet as I'm stuck on this issue. I'm optimistic that I can handle creating the label lists but not sure yet how I'll pass those lists to the classes.
I was originally trying to create a sub-sub forms, where first I would iterate over the number of communities and then iterate of the number of militants (for example), but I couldn't access the data from all of the fields using form.affiliations.data this way. So it is absolutely necessary that I change these subfield labels in order to distinguish between Community 1 and its subsections Militant1, Militant2... etc.
If its possible to remove the default subfield labels completely and add my own text between each field instance, that would also work.
I solved this problem by using Javascript in my HTML templates to find the labels based on their names hidden in the page. I then replaced them with the label names I prefer. For example, where the unwanted label occurring was regionpercent-0, I used the following code:
var label = document.querySelector('label[for="regionpercent-0"]') !==null;
if (label) {
var label = document.querySelector('label[for="regionpercent-0"]');
label.textContent = '{{ region_percent_list[0] }}';
}
where region_percent_list[0] is the variable name for the actual label that I wanted to use.