'How to send table dropdown select fields to flask
I have a table composed of three columns, a text and two other select
fields.
When the user chooses an option from the dropdown select
, I would like to send these data to flask.
I know I can make it work with input
s but since I am working with select
, I am not sure how I can send them back to flask.
This is my table:
<div class="row" id="tablediv">
<div class="col">
<table class="table table-striped table-bordered" id="table"/>
</div>
</div>
const office_cardgroups = data['cardgroups']
const office_doorgroups = data['doorgroups']
const table = document.getElementById("table");
const header = table.createTHead();
var row = header.insertRow(0);
row.insertCell(0).innerHTML = "<b>Departments</b>";
row.insertCell(1).innerHTML = "<b>Card Groups</b>";
row.insertCell(2).innerHTML = "<b>Door Groups</b>";
{% for department in departments %}
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
row.insertCell(0).innerHTML = "{{ department.name }}";
var row_cardgroup = '<td className="select"><select id="cardgroups_{{ department.id }}">'
for (const [key, cardgroup] of Object.entries(office_cardgroups)) {
var row_cardgroup = row_cardgroup + '<option value=' + cardgroup['id'] + '>'+ cardgroup['name']+'</option>'
}
row_cardgroup = row_cardgroup + '</select></td>'
row.insertCell(1).innerHTML = row_cardgroup
var row_doorgroup = '<td className="select"><select id="cardgroups_{{ department.id }}">'
for (const [key, doorgroup] of Object.entries(office_doorgroups)) {
var row_doorgroup = row_doorgroup + '<option value=' + doorgroup['id'] + '>'+ doorgroup['name']+'</option>'
}
row_doorgroup = row_doorgroup + '</selec></td>'
row.insertCell(2).innerHTML = row_doorgroup
{% endfor %}
Solution 1:[1]
There are few issues in the shared code:
table
tag is not self closing so it should be
<table class="table table-striped table-bordered" id="table"></table>
- Not sure where
data['cardgroups']
anddata['doorgroups']
are coming from, If they are coming from backend tojinja
template then it should be wrapped with parenthesis{{}}
- Since you are writing javascript it should be inside
script
tag id
should be unique across html right now we have 2 id with same namecardgroups_{{ department.id }}
in select
Data used in example
data = {
"departments": [{
"id": 1,
"name": "Dept 1",
}, {
"id": 2,
"name": "Dept 2",
}, {
"id": 3,
"name": "Dept 3",
}],
"cardgroups": [{
"id": 4,
"name": "Card 1",
}, {
"id": 5,
"name": "Card 2",
}, {
"id": 6,
"name": "Card 3",
}],
"doorgroups": [{
"id": 7,
"name": "Door 1",
}, {
"id": 8,
"name": "Door 2",
}, {
"id": 9,
"name": "Door 3",
}],
}
There are 2 ways you can send data to backend
Using form
You can wrap the table with form with submit button and add name in select tag which would then make the data available in request.form
<div class="row" id="tablediv">
<div class="col">
<form method="POST">
<table class="table table-striped table-bordered" id="table"></table>
<input type="submit" />
</form>
</div>
</div>
<script>
const office_cardgroups = {{ data['cardgroups'] | safe }}
const office_doorgroups = {{ data['doorgroups'] | safe }}
const table = document.getElementById("table");
const header = table.createTHead();
var row = header.insertRow(0);
row.insertCell(0).innerHTML = "<b>Departments</b>";
row.insertCell(1).innerHTML = "<b>Card Groups</b>";
row.insertCell(2).innerHTML = "<b>Door Groups</b>";
{% for department in data['departments'] %}
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
row.insertCell(0).innerHTML = "{{ department.name }}";
var row_cardgroup = '<td className="select"><select name="cardgroups_{{ department.id }}">'
for (const [key, cardgroup] of Object.entries(office_cardgroups)) {
var row_cardgroup = row_cardgroup + '<option value=' + cardgroup['id'] + '>'+ cardgroup['name']+'</option>'
}
row_cardgroup = row_cardgroup + '</select></td>'
row.insertCell(1).innerHTML = row_cardgroup
var row_doorgroup = '<td className="select"><select name="doorgroups_{{ department.id }}">'
for (const [key, doorgroup] of Object.entries(office_doorgroups)) {
var row_doorgroup = row_doorgroup + '<option value=' + doorgroup['id'] + '>'+ doorgroup['name']+'</option>'
}
row_doorgroup = row_doorgroup + '</selec></td>'
row.insertCell(2).innerHTML = row_doorgroup
{% endfor %}
</script>
@app.route('/', methods=["GET", "POST"])
def index():
print(request.form)
return render_template('index.html', data=data)
Using javascript
<div class="row" id="tablediv">
<div class="col">
<table class="table table-striped table-bordered" id="table"></table>
<button id="send-data">Submit</button>
</div>
</div>
<script>
const office_cardgroups = {{ data['cardgroups'] | safe }}
const office_doorgroups = {{ data['doorgroups'] | safe }}
const table = document.getElementById("table");
const header = table.createTHead();
var row = header.insertRow(0);
row.insertCell(0).innerHTML = "<b>Departments</b>";
row.insertCell(1).innerHTML = "<b>Card Groups</b>";
row.insertCell(2).innerHTML = "<b>Door Groups</b>";
{% for department in data['departments'] %}
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
row.insertCell(0).innerHTML = "{{ department.name }}";
var row_cardgroup = '<td className="select"><select id="cardgroups_{{ department.id }}">'
for (const [key, cardgroup] of Object.entries(office_cardgroups)) {
var row_cardgroup = row_cardgroup + '<option value=' + cardgroup['id'] + '>'+ cardgroup['name']+'</option>'
}
row_cardgroup = row_cardgroup + '</select></td>'
row.insertCell(1).innerHTML = row_cardgroup
var row_doorgroup = '<td className="select"><select id="doorgroups_{{ department.id }}">'
for (const [key, doorgroup] of Object.entries(office_doorgroups)) {
var row_doorgroup = row_doorgroup + '<option value=' + doorgroup['id'] + '>'+ doorgroup['name']+'</option>'
}
row_doorgroup = row_doorgroup + '</selec></td>'
row.insertCell(2).innerHTML = row_doorgroup
{% endfor %}
const departments = {{ data['departments'] | safe }}
document.querySelector('#send-data').addEventListener('click', function() {
const form_data = new FormData();
departments.forEach(function(department) {
let card_id = `cardgroups_${department.id}`;
form_data.append(card_id, document.querySelector("#" + card_id).value);
let door_id = `doorgroups_${department.id}`;
form_data.append(door_id, document.querySelector("#" + door_id).value);
})
const url = 'http://localhost:5000/';
const xhr = new XMLHttpRequest();
xhr.open( 'POST', url, true );
// xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.onreadystatechange = function ( response ) {};
xhr.send( form_data );
// using jQuery
// $.ajax({
// url: url,
// data: form_data,
// processData: false,
// contentType: false,
// type: 'POST',
// success: function(data){
// alert(data);
// }
// });
});
</script>
@app.route('/', methods=["GET", "POST"])
def index():
print(request.form)
return render_template('index.html', data=data)
Improvement: Template just using jinja no javascript
<div class="row" id="tablediv">
<div class="col">
<table class="table table-striped table-bordered" id="table">
{% for department in data['departments'] %}
<tr>
<td>{{ department.name }}</td>
<td className="select">
<select id="cardgroups_{{ department.id }}">
{% for card in data['cardgroups'] %}
<option value='{{ card.id }}'>{{ card.name }}</option>
{% endfor %}
</select>
</td>
<td className="select">
<select id="doorgroups_{{ department.id }}">
{% for door in data['doorgroups'] %}
<option value='{{ door.id }}'>{{ door.name }}</option>
{% endfor %}
</select>
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
Note: If you want to send on each select value separately you can addEventListener
to each select.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |