update the value of a drop down filter according to the entry of the first
Question:
I’m developing a flask application that filters the value of a Mysql database table and depending on the selected value of the first drop down it will update the value of the second drop down. and then finally return some data
now the code is working but there seems to be bug in the code, such that when i make a new selection from the first drop down it will populate the second drop down with the values of the first drop down together with the expected values of the second drop down
it should not do that i expected it to only populate the second drop down with the expected values and not add the values of the first drop down together with it.
this is my flask application code:
from flask import jsonify, request
from flask import Flask, render_template
import mysql.connector
app = Flask(__name__)
# Configure MySQL connection
cnx = mysql.connector.connect(
host="xxxxxxx",
user="xxxxxxxxx",
password="xxxxxxxxx",
database="xxxxxxxxxx")
@app.route('/', methods=['GET', 'POST'])
def index():
try:
cursor = cnx.cursor()
query = "SELECT topic FROM text_table"
cursor.execute(query)
data = [row[0] for row in cursor.fetchall()] # Get the first column of all rows
cursor.nextset() # consume any unread result
cursor.close()
if request.method == 'POST':
selected_topic = request.form.get('selected_topic') # Get the selected topic from the form
if selected_topic:
cursor = cnx.cursor()
query = "SELECT sub_topic FROM text_table WHERE topic = %s"
cursor.execute(query, (selected_topic,))
sub_topics = [row[0] for row in cursor.fetchall()] # Get the sub topics for the selected topic
cursor.nextset()
selected_sub_topic = request.form.get('selected_sub_topic') # Get the selected sub topic from the form
if selected_sub_topic:
query = "SELECT text FROM text_table WHERE topic = %s AND sub_topic = %s"
cursor.execute(query, (selected_topic, selected_sub_topic))
result = cursor.fetchone()[0] # Get the value of the text for the selected sub topic
cursor.nextset()
cursor.close()
return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics, selected_sub_topic=selected_sub_topic, result=result)
cursor.close()
return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics)
return render_template('index.html', topics=data)
except Exception as e:
# Return an error message if there's an exception
return jsonify(error=str(e)), 500
if __name__ == '__main__':
app.run()
this is my html code with a little bit of javascript
<!DOCTYPE html>
<html>
<head>
<title>Drop Down Filter</title>
<script>
function updateSubTopics() {
var selectTopic = document.getElementById("selected_topic");
var selectSubTopic = document.getElementById("selected_sub_topic");
var selectedTopicValue = selectTopic.value;
// Send a POST request to update the sub topic options
var xhr = new XMLHttpRequest();
xhr.open('POST', '/');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
if (xhr.status === 200) {
// Update the sub topic options
selectSubTopic.innerHTML = xhr.responseText;
// Check if the currently selected sub topic is valid for the new selected topic
var subTopicOptions = selectSubTopic.options;
var foundSelectedSubTopic = false;
for (var i = 0; i < subTopicOptions.length; i++) {
if (subTopicOptions[i].value === selectSubTopic.value) {
foundSelectedSubTopic = true;
break;
}
}
if (!foundSelectedSubTopic) {
selectSubTopic.value = "";
}
}
else {
console.log('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send('selected_topic=' + selectedTopicValue);
}
</script>
</head>
<body>
<form method="POST">
<select name="selected_topic" id="selected_topic" onchange="updateSubTopics()">
{% for topic in topics %}
<option value="{{ topic }}"
{% if selected_topic == topic %}selected{% endif %}>
{{ topic }}
</option>
{% endfor %}
</select>
<select name="selected_sub_topic" id="selected_sub_topic">
{% for sub_topic in sub_topics %}
<option value="{{ sub_topic }}"
{% if selected_sub_topic == sub_topic %}selected{% endif %}>
{{ sub_topic }}
</option>
{% endfor %}
</select>
<input type="submit" value="Filter">
</form>
{% if result %}
<h1>{{ result }}</h1>
{% endif %}
</body>
</html>
thank you, any help will be greatly appreciated
Answers:
The problem occurs when you are sending a template response after filtering.
return render_template(‘index.html’, topics=data, selected_topic=selected_topic, sub_topics=sub_topics)
You already have rendered index.html however you also are rendering index.html when the select option is changed from this line.
selectSubTopic.innerHTML = xhr.responseText;
What this basically means is that you are pasting all your html code inside select element which you can check by inspecting in your browser.
In my opinion, What should be done is that you should only send a python dictionary as a response for sub topics.
if selected_topic:
cursor = cnx.cursor()
query = "SELECT sub_topic FROM text_table WHERE topic = %s"
cursor.execute(query, (selected_topic,))
sub_topics = [row[0] for row in cursor.fetchall()] # Get the sub topics for the selected topic
cursor.nextset()
selected_sub_topic = request.form.get('selected_sub_topic') # Get the selected sub topic from the form
if selected_sub_topic:
query = "SELECT text FROM text_table WHERE topic = %s AND sub_topic = %s"
cursor.execute(query, (selected_topic, selected_sub_topic))
result = cursor.fetchone()[0] # Get the value of the text for the selected sub topic
cursor.nextset()
cursor.close()
return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics, selected_sub_topic=selected_sub_topic, result=result)
cursor.close()
return sub_topics
After successfully getting the dictionary, the response will be in format so it needs to be parsed to json. Then you can use a JS loop to create loops and append it to your sub_topic select item.
if (xhr.status === 200) {
selectSubTopic.options.length = 0;
var subTopicOptions = JSON.parse(xhr.responseText);
for (var i = 0; i < subTopicOptions.length; i++) {
var option = document.createElement('option');
option.text = subTopicOptions[i];
option.value = subTopicOptions[i];
selectSubTopic.appendChild(option);
}
// Check if the currently selected sub topic is valid for the new selected topic
var subTopicOptions = selectSubTopic.options;
var foundSelectedSubTopic = false;
for (var i = 0; i < subTopicOptions.length; i++) {
if (subTopicOptions[i].value === selectSubTopic.value) {
foundSelectedSubTopic = true;
break;
}
}
if (!foundSelectedSubTopic) {
selectSubTopic.value = "";
}
}
else {
console.log('Request failed. Returned status of ' + xhr.status);
}
I’m developing a flask application that filters the value of a Mysql database table and depending on the selected value of the first drop down it will update the value of the second drop down. and then finally return some data
now the code is working but there seems to be bug in the code, such that when i make a new selection from the first drop down it will populate the second drop down with the values of the first drop down together with the expected values of the second drop down
it should not do that i expected it to only populate the second drop down with the expected values and not add the values of the first drop down together with it.
this is my flask application code:
from flask import jsonify, request
from flask import Flask, render_template
import mysql.connector
app = Flask(__name__)
# Configure MySQL connection
cnx = mysql.connector.connect(
host="xxxxxxx",
user="xxxxxxxxx",
password="xxxxxxxxx",
database="xxxxxxxxxx")
@app.route('/', methods=['GET', 'POST'])
def index():
try:
cursor = cnx.cursor()
query = "SELECT topic FROM text_table"
cursor.execute(query)
data = [row[0] for row in cursor.fetchall()] # Get the first column of all rows
cursor.nextset() # consume any unread result
cursor.close()
if request.method == 'POST':
selected_topic = request.form.get('selected_topic') # Get the selected topic from the form
if selected_topic:
cursor = cnx.cursor()
query = "SELECT sub_topic FROM text_table WHERE topic = %s"
cursor.execute(query, (selected_topic,))
sub_topics = [row[0] for row in cursor.fetchall()] # Get the sub topics for the selected topic
cursor.nextset()
selected_sub_topic = request.form.get('selected_sub_topic') # Get the selected sub topic from the form
if selected_sub_topic:
query = "SELECT text FROM text_table WHERE topic = %s AND sub_topic = %s"
cursor.execute(query, (selected_topic, selected_sub_topic))
result = cursor.fetchone()[0] # Get the value of the text for the selected sub topic
cursor.nextset()
cursor.close()
return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics, selected_sub_topic=selected_sub_topic, result=result)
cursor.close()
return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics)
return render_template('index.html', topics=data)
except Exception as e:
# Return an error message if there's an exception
return jsonify(error=str(e)), 500
if __name__ == '__main__':
app.run()
this is my html code with a little bit of javascript
<!DOCTYPE html>
<html>
<head>
<title>Drop Down Filter</title>
<script>
function updateSubTopics() {
var selectTopic = document.getElementById("selected_topic");
var selectSubTopic = document.getElementById("selected_sub_topic");
var selectedTopicValue = selectTopic.value;
// Send a POST request to update the sub topic options
var xhr = new XMLHttpRequest();
xhr.open('POST', '/');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
if (xhr.status === 200) {
// Update the sub topic options
selectSubTopic.innerHTML = xhr.responseText;
// Check if the currently selected sub topic is valid for the new selected topic
var subTopicOptions = selectSubTopic.options;
var foundSelectedSubTopic = false;
for (var i = 0; i < subTopicOptions.length; i++) {
if (subTopicOptions[i].value === selectSubTopic.value) {
foundSelectedSubTopic = true;
break;
}
}
if (!foundSelectedSubTopic) {
selectSubTopic.value = "";
}
}
else {
console.log('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send('selected_topic=' + selectedTopicValue);
}
</script>
</head>
<body>
<form method="POST">
<select name="selected_topic" id="selected_topic" onchange="updateSubTopics()">
{% for topic in topics %}
<option value="{{ topic }}"
{% if selected_topic == topic %}selected{% endif %}>
{{ topic }}
</option>
{% endfor %}
</select>
<select name="selected_sub_topic" id="selected_sub_topic">
{% for sub_topic in sub_topics %}
<option value="{{ sub_topic }}"
{% if selected_sub_topic == sub_topic %}selected{% endif %}>
{{ sub_topic }}
</option>
{% endfor %}
</select>
<input type="submit" value="Filter">
</form>
{% if result %}
<h1>{{ result }}</h1>
{% endif %}
</body>
</html>
thank you, any help will be greatly appreciated
The problem occurs when you are sending a template response after filtering.
return render_template(‘index.html’, topics=data, selected_topic=selected_topic, sub_topics=sub_topics)
You already have rendered index.html however you also are rendering index.html when the select option is changed from this line.
selectSubTopic.innerHTML = xhr.responseText;
What this basically means is that you are pasting all your html code inside select element which you can check by inspecting in your browser.
In my opinion, What should be done is that you should only send a python dictionary as a response for sub topics.
if selected_topic:
cursor = cnx.cursor()
query = "SELECT sub_topic FROM text_table WHERE topic = %s"
cursor.execute(query, (selected_topic,))
sub_topics = [row[0] for row in cursor.fetchall()] # Get the sub topics for the selected topic
cursor.nextset()
selected_sub_topic = request.form.get('selected_sub_topic') # Get the selected sub topic from the form
if selected_sub_topic:
query = "SELECT text FROM text_table WHERE topic = %s AND sub_topic = %s"
cursor.execute(query, (selected_topic, selected_sub_topic))
result = cursor.fetchone()[0] # Get the value of the text for the selected sub topic
cursor.nextset()
cursor.close()
return render_template('index.html', topics=data, selected_topic=selected_topic, sub_topics=sub_topics, selected_sub_topic=selected_sub_topic, result=result)
cursor.close()
return sub_topics
After successfully getting the dictionary, the response will be in format so it needs to be parsed to json. Then you can use a JS loop to create loops and append it to your sub_topic select item.
if (xhr.status === 200) {
selectSubTopic.options.length = 0;
var subTopicOptions = JSON.parse(xhr.responseText);
for (var i = 0; i < subTopicOptions.length; i++) {
var option = document.createElement('option');
option.text = subTopicOptions[i];
option.value = subTopicOptions[i];
selectSubTopic.appendChild(option);
}
// Check if the currently selected sub topic is valid for the new selected topic
var subTopicOptions = selectSubTopic.options;
var foundSelectedSubTopic = false;
for (var i = 0; i < subTopicOptions.length; i++) {
if (subTopicOptions[i].value === selectSubTopic.value) {
foundSelectedSubTopic = true;
break;
}
}
if (!foundSelectedSubTopic) {
selectSubTopic.value = "";
}
}
else {
console.log('Request failed. Returned status of ' + xhr.status);
}