kramer65
kramer65

Reputation: 54033

How to insert conditional fields with WTForms?

In a website I'm building with Flask I'm using WTForms for form validation. I currently have a field which is dependent on another field: if a user inserts a specific year (2012) a couple radio buttons are inserted using Javascript. I made the RadioField optional, which works fine, but if I actually do submit the form with the radiobuttons the value of it remains None.

To talk some code; the two relevant form fields are defined as follows:

construction_year = IntegerField('construction_year')
transfer_tax_rate = SelectField('transfer_tax_rate', validators=[Optional()], choices=[('ZERO', '0%'), ('SIX', '6%')])

the code I first used in the template to display the construction_year and transfer_tax_rate is as follows:

{{ form.construction_year(size=10) }}
{{ form.transfer_tax_rate() }}

This works fine; I can print out the values on the back end like so:

if form.validate_on_submit():
    print form.construction_year.data  # prints out '2012'
    print form.transfer_tax_rate.data  # prints out ZERO or SIX depending on my choice

I then removed {{ form.transfer_tax_rate() }} and wrote some Javascript which inserts the some html if the construction_year is 2012:

function displayTransferTaxRate(){
    var year = $("#construction_year").val();
    var propertyType = $("#property_type").val();
    if (year.length == 4 && year == 2012) {
        var transferTaxRateHtml = 'Applicable tax rate <select id="transfer_tax_rate" name="transfer_tax_rate"><option value="ZERO">0%</option><option value="SIX">6%</option></select>';
        $('#transfer-tax-rate-div').html(transferTaxRateHtml);
    } else {
        $('#transfer-tax-rate-div').html('');
    }
}
$("#construction_year").on('keyup paste', displayTransferTaxRate);

for easy reading; the html it inserts is as follows:

<select id="transfer_tax_rate" name="transfer_tax_rate">
    <option value="ZERO">0%</option>
    <option value="SIX">6%</option>
</select>

The html gets inserted fine, and I can select either of the options. But when I submit the form and try to get the value of the transfer_tax_rate as follows, it always prints out None:

if form.validate_on_submit():
    print form.construction_year.data  # prints out '2012'
    print form.transfer_tax_rate.data  # prints out None

Does anybody have any idea what I'm doing wrong here? All tips are welcome!

[EDIT] Following the tip from user3147268 below I aslo tried getting it from the standard flask request.form, but that doesn't contain an entry for 'transfer_tax_rate' either.

Upvotes: 4

Views: 3013

Answers (1)

kramer65
kramer65

Reputation: 54033

Okay, after about 5 hours of banging my head against the wall, I'll answer my own question, because you guys could not have known this.

It turns out that it was related to a table in which this form was embedded. I left that information out, because I didn't expect that to be relevent.

So this works fine:

<table>
    <form action="" method="post" id="prop-form">
        {{ form.hidden_tag() }}
        <tr>
            <td>Construction year: </td>
            <td>
                {{ form.construction_year(size=10) }}
            </td>
        </tr>
        <tr>
            <td>Transfer tax rate: </td>
            <td>
                {{ form.transfer_tax_rate()
            </td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="Save property"></td>
        </tr>
    </form>
</table>

But when I add the exact same html in this div, it doesn't work anymore:

<table>
    <form action="" method="post" id="prop-form">
        {{ form.hidden_tag() }}
        <tr>
            <td>Construction year: </td>
            <td>
                {{ form.construction_year(size=10) }}
                <div id="transfer-tax-rate-div"></div>
            </td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="Save property"></td>
        </tr>
    </form>
</table>

whereas, without the table around it, it does work:

<form action="" method="post" id="prop-form">
{{ form.hidden_tag() }}
Construction year: {{ form.construction_year(size=10) }} <br />
<div id="transfer-tax-rate-div"></div>
<input type="submit" value="Save property">
</form>

The solution turned out to lie in the placement of the <form> tags, because if I move them out of the table like this last piece of code, it all works fine:

<form action="" method="post" id="prop-form">
{{ form.hidden_tag() }}
<table>
    <tr>
        <td>Construction year: </td>
        <td>
            {{ form.construction_year(size=10) }}
            <div id="transfer-tax-rate-div"></div>
        </td>
    </tr>
    <tr>
        <td></td>
        <td><input type="submit" value="Save property"></td>
    </tr>
</table>
</form>

Excuse me for bothering all you guys and girls time whilst not providing all the relevant information. Thank you for giving me the energy to keep on looking though!

Upvotes: 4

Related Questions