WTFox
WTFox

Reputation: 171

Dynamically update SelectField based on another SelectField's data?

I'm having a bit of an issue with this. Here's an overview of what I've created: a simple form with 2 select fields, 1 file upload field, and a submit button. The first select will pull it's choices from sql database (I have that finished) Then based on what the user selects from SelectField1, SelectField2 will populate with it's results from the SQL database. I'd like this to happen upon selection in number 1. In other words, Have selectfield2 dynamically update/populate itself without refreshing the page.

The workflow will go something like this:

Can anyone point me in the right direction? I'm working on this at home over the weekend so I don't have a connection to the database. I've created 3 lists to test with.

I've tried doing something like:

if form.sf_baclient.data == 'py':
    form.sf_clientplan.choices = list2
else:
    form.sf_clientplan.choices = list3

but that didn't do a live update. Here's the code for the html and the view:

HTML

    <form action="{{ url_for('index') }}" method=post>
        {{ form.hidden_tag() }}
        <dl>
            {{ form.sf_baclient.label }}<br>
            {{ form.sf_baclient }}<br>

            {{ form.sf_clientplan.label }}<br>
            {{ form.sf_clientplan }}<br>

            {{ form.ff_pdf_upload.label }}<br>
            {{ form.ff_pdf_upload }}<br>

        </dl>
        {{ form.sb_submit }}
    </form>

View

@app.route('/', methods=['GET', 'POST'])
def index():

form = MyForm(request.form)

list1 = [('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')]
list2 = [('1', 'One'), ('2', 'Two'), ('3', 'Three')]
list3 = [('blue', 'Blue'), ('red', 'Red'), ('green', 'Green')]

form.sf_baclient.choices = list1
form.sf_baclient.choices.insert(0, ('', ''))

form.sf_clientplan.choices = list3
form.sf_clientplan.choices.insert(0, ('', ''))

if request.method == 'GET':
    return render_template('home.html', form=form)

elif request.method == 'POST':
    if form.sb_submit.data == True:
        message = form.sf_baclient.data
        # flash(message)

    return render_template('home.html', form=form, success=True)

Upvotes: 3

Views: 6451

Answers (2)

WTFox
WTFox

Reputation: 171

Most of this has to be scripted on the client side. This is what I ended up doing. Let me know if it's not clear enough.

Create a route and url in your views file to handle processing. I usually start these with an underscore and the word parse. See below.

@app.route('/_parse_data', methods=['GET'])
def parse_data():
    if request.method == "GET":

        # only need the id we grabbed in my case. 
        id = request.args.get('b', 0)
        new_list = _call_to_db(id)

        # When returning data it has to be jsonify'ed and a list of tuples (id, value) to populate select fields.
        # Example: [('1', 'One'), ('2', 'Two'), ('3', 'Three')]

    return jsonify(new_list)

You're going to need to determine the selection using javascript/jquery. So in my javascript I wrote this.

    $('#sf_baclient').on('change', function() {

            $("#sf_clientplan").empty();

            baclient_name = $("#sf_baclient option:selected").text();
            baclient_id = $("#sf_baclient option:selected").val();

            # Sending variables containing selection info to parse_data function in python.
            # jQuery's builtin ajax functions make things super easy 

            # Calling that parse url and sending it arguments
            $.getJSON($SCRIPT_ROOT + '/_parse_data', {
                a: baclient_name,
                b: baclient_id

            # Function to get data returned from parse_data and populate the second select field. 
            }, function(data) {
                # Using jQuery to populate new entries we got from flask.
                var options = $("#sf_clientplan");
                $.each(data, function() {
                    options.append($("<option />").val(this).text(this));
                });

            });

Upvotes: 4

AutonomouSystem
AutonomouSystem

Reputation: 21

if 'py' in form.sf_baclient.data:
    form.sf_clientplan.choices = list2
else:
    form.sf_clientplan.choices = list3

Logically it should work similarly to what you have. I know your goal is for it to live update, try wrapping it in a while loop, something that activates when form.sf_baclient.data has data.

Upvotes: 0

Related Questions