I have an application that is using Flask and wtforms and part of the functionality is to take user input for the first two fields and populate the remainder of the form fields which are of type SelectMultipleField (I'm going to refer to these as select fields) with choices from a database based on the first two fields (I'm going to refer to these as entry fields).
My issue right now is getting the select fields to dynamically populate. I found a solution here and this seems to be exactly what I need. It instantiates the select fields to all possible choices and then when it detects a JQuery "onchange" event in the entry fields, filters the select fields to choices based on the user entry for the entry fields. An example would be a user entering a specific company into the form and the select fields populating with "locations" only for that company.
However, in adapting this solution to my problem, I have not been able to get the code to run and I have researched far and wide and unable to resolve this. I'm new to both JQuery and Stack Overflow so any help would be greatly appreciated. Below is my code. Note that I am only focusing on one of the entry fields and dynamically populating just one of the select fields until I get this to work. Test_table is the entry field and test_join_key is the select field.
Here's the form with relevant fields-
class QaForm(FlaskForm):
test_table_in = StringField('Test Table', validators=[DataRequired()], id= 'test_table')
test_join_key = SelectMultipleField("Select Test Fields to Join on", choices=[], coerce=str, id = 'select_test_join_key')
Flask view to instantiate all the select fields -
@app.route('/', methods = ['GET', 'POST'])
@app.route('/home', methods = ['GET', 'POST'])
def home():
form = QaForm()
fields_query = f"""select column_name AS Fields from information_schema.columns group by 1;"""
conn.execute(fields_query)
result = conn.fetchall()
select_choices = [(column, column) for column in result]
form.test_join_key.choices = select_choices
Flask view to get choices for select fields based on user input for entry field -
@app.route('/_get_fields/<table>')
def _get_fields(table):
table = request.args.get(table, type=str)
fields_query = f"""select column_name AS Fields from information_schema.columns WHERE table_name = '{table}' group by 1;"""
conn.execute(fields_query)
result = conn.fetchall()
select_choices = [(column, column) for column in result]
return jsonify(select_choices)
JQuery to detect input in entry field and filter choices for select field (injected in HTML file)-
<script charset="utf-8" type="text/javascript">
$function() {
var dropdown = {
test_table: $('#test_table')
test_join_key: $('#select_test_join_key')
}
updateFields();
function updateFields() {
var send = {
test_table: dropdown.test_table.val()
};
dropdown.test_join_key.attr('disabled', 'disabled');
dropdown.test_join_key.empty();
$.getJSON("{{url_for('_get_fields') }}", send, function(data) {
data.forEach(function(item) {
dropdown.test_join_key.append(
$('<option>', {
value: item[0],
text: item[1]
})
);
});
dropdown.test_join_key.removeAttr('disabled');
});
}
dropdown.test_table.on('change', function() {
updateFields();
});
});
</script>
EDIT: Using @Ibsn suggestions, I was able to get the JQuery snippet to run for one form field. However, updating it to perform the same actions for multiple fields using parameters for the function again results in the code not running. I've checked to make sure my syntax is correct based on the tutorial on W3 schools as well as other Stack Overflow questions but still unable to get it to run. Here's the updated Jquery to detect input in entry fields and filter choices for select fields -
<script charset="utf-8" type="text/javascript">
$(function() {
var tables = {
test_table: $('#test_table'),
prod_table: $('#prod_table')
};
var fields = {
test_join_key: $('#select_test_join_key'),
prod_join_key: $('#select_prod_join_key'),
test_dimensions: $('#select_test_dimensions'),
prod_dimensions: $('#select_prod_dimensions'),
test_measures: $('#select_test_measures'),
prod_measures: $('#select_prod_measures')
};
updateFields(table, field);
function updateFields(table, field) {
var send = {
table: tables.table.val()
};
fields.field.attr('disabled', 'disabled');
fields.field.empty();
$.getJSON("{{url_for('_get_fields') }}", send, function(data) {
data.forEach(function(item) {
fields.field.append(
$('<option>', {
value: item[1],
text: item[0]
})
);
});
fields.field.removeAttr('disabled');
});
}
tables.test_table.on('change', function() {
updateFields(tables.test_table, fields.test_join_key);
updateFields(tables.test_table, fields.test_dimensions);
updateFields(tables.test_table, fields.test_measures);
});
tables.prod_table.on('change', function() {
updateFields(tables.prod_table, fields.prod_join_key);
updateFields(tables.prod_table, fields.prod_dimensions);
updateFields(tables.prod_table, fields.prod_measures);
});
});