0

I'm having a heck of a time with this. I think I've gotten close looking at similar problems people have had but can't seem to bust through. I have a pair of drop down menus: The first has a list of 3 choices and the second populates with the same list less whichever you picked from the first. All of this works. My problem is that the second will not validate, throwing a 'Not a valid choice' error. Googling has got me as far as suspecting an issue with the object type. It is coming across as str, and I see that the default behavior of SelectField is coerce=unicode. I've tried to coerce as str without success. Anyways, I would appreciate any help. Below is my relevant code:

template.py-

{% extends "header.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block body %}
<form method="POST" action="/form_test/">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
    <div class="form-group col-md-4 text-left">
        <h3 align="center">Router 1</h3>
            {{ wtf.form_field(form.isp_r1) }}
    </div>
    <div class="form-group col-md-4 text-left">
        <h3 align="center">Router 1</h3>
            {{ wtf.form_field(form.isp_r2) }}
    </div>
     <div class="container">
        <button type="submit" class="btn btn-primary" value="Create">Submit</button>
    </div>
</form>

forms.py

from flask_wtf import FlaskForm
from wtforms import BooleanField, StringField, IntegerField, SelectField
from wtforms.validators import InputRequired, required, Length, IPAddress, ValidationError, NumberRange
class test_form(FlaskForm):
    isp_r1 = SelectField('ISP', validators=[required()], coerce=str, choices=[("", "Please Choose"), ("1", "AT&T"), ("2", "Level3"), ("3", "Sprint")], render_kw={"placeholder": "San Antonio, TX", "onchange": "populateispwtf(this.id,'isp_r2')"})
    isp_r2 = SelectField('ISP', coerce=str, validators=[InputRequired()], choices=[("", "---")])

custom.js-

function populateispwtf(s1,s2) {
    var s1 = document.getElementById(s1);
    var s2 = document.getElementById(s2);
    s2.innerHTML = "";
    if(s1.value == "1") {
        var optionArray = ["|",
                           "2|Level 3",
                           "3|Sprint",];
    } else if(s1.value == "2") {
        var optionArray = ["|",
                           "1|AT&T",
                           "3|Sprint",];
    } else if(s1.value == "3") {
        var optionArray = ["|",
                           "1|AT&T",
                           "2|Level 3",];

    } console.log(optionArray);
    for(var option in optionArray) {
        var pair = optionArray[option].split("|");
        var newOption = document.createElement("option");
        newOption.value = pair[0];
        newOption.innerHTML = pair[1];
        s2.options.add(newOption);
    }
}
Steve B
  • 75
  • 1
  • 8

1 Answers1

2

This really didn't get any traffic but, for the sake of anyone who may come across this with the same issue:

'Not a valid choice' is actually referring to the list of choices in the wtform itself. (choices=[('val1', 'Choice 1 Text'), ('val2', 'Choice 2 Text')] etc). Because I was using javascript to populate the selectfield after it had already rendered, the html changed but the available choices didn't, so far as wtforms was concerned. The solution was in the pre-validation and I found the solution here so all credit to Mark Hildreth

I won't bother repeating what he said because my solution was a straight lift of his. I just wanted to point to his in case someone struggling with dynamic population of selectfields (and cascading menus) found my post first.

Steve B
  • 75
  • 1
  • 8