3

I am creating a flask form where I need to show a dropdown based on some other dropdown select field in Flask. I was able to do it with HTML, but finding it difficult to do the same in Flask form.

routes.py :

class RegistrationForm(FlaskForm):
    category = SelectField('Category', choices = [('Clothes', 'Clothes'), ('Watch', 'Watch')])
    subcategory = SelectField('Sub Category', choices = [('USPA', 'USPA'), ('LEE', 'LEE'), ('FOSSIL', 'FOSSIL'), ('TITAN', 'TITAN')])
    submit = SubmitField('Register')

HTML :

<form action="" method="post">
    {{ form.hidden_tag() }}
    <p>
    <p>
        {{ form.category.label }}<br>
        {{ form.category }}<br>
        {% for error in form.category.errors %}
        <span style="color: red;">[{{ error }}]</span>
        {% endfor %}
    </p>
    <p>
        {{ form.subcategory.label }}<br>
        {{ form.subcategory }}<br>
        {% for error in form.subcategory.errors %}
        <span style="color: red;">[{{ error }}]</span>
        {% endfor %}
    </p>
    <p>{{ form.submit() }}</p>
</form>

I want mapping link this :

Clothes : USPA, LEE

Watch : FOSSIL, TITAN

But in the form I am getting all the options. I need subcategory based on selected category.

Community
  • 1
  • 1
  • Hey there, would using a select box with categories (option groups) also be an option? Check out [selectize.js](https://selectize.github.io/selectize.js/) – Uralan Nov 14 '19 at 12:45

1 Answers1

6

Since this is dynamic functionality on the client side you will need to use Javascript.

Personally I think the easiest way to do this is pre configure your flask form statically:

class RegistrationForm(FlaskForm):
    category = SelectField('Category', choices = [('Clothes', 'Clothes'), ('Watch', 'Watch')])
    subcategory_clothes = SelectField('Sub Category', choices = [('USPA', 'USPA'), ('LEE', 'LEE')], validators=[Optional()])
    subcategory_watches = SelectField('Sub Category', choices = [('Titan', 'Titan'), ('Fossil', 'Fossil')], validators=[Optional()])
    submit = SubmitField('Register')

And then display either one or the other combo boxes dependent upon the value of the initial combo box, using Javascript if statement. You will need a javascript event hook to detect changes to category, or use a framework such as Vue.js.

An example of javascript hook is here https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onchange

You can add a javascript function, in HTML, to show either box depending on the value of the other checkbox:

<script>
function myFunction() {
  let box_value = document.getElementById("category").value;
  if (box_value === "Clothes") {
    document.getElementById("subcategory_clothes").style.display = "initial"
    document.getElementById("subcategory_watches").style.display = "none"
  } else {
    document.getElementById("subcategory_clothes").style.display = "none"
    document.getElementById("subcategory_watches").style.display = "initial"
  }
}
</script>

And you can add a render_keyword argument in Python so that it populates the event hook in HTML:

category = SelectField('Category', choices = [('Clothes', 'Clothes'), ('Watch', 'Watch')], render_kw={'onchange': "myFunction()"})
Attack68
  • 4,437
  • 1
  • 20
  • 40