'Pass HTML table rows to Flask backend
I have a Flask app where I populate an HTML table using javascript when the user presses a button. I need the info from the table passed back to the backend when the user is done with the table and presses another button. I'm trying to access the td elements using Flask's request.form
Javascript:
let i = 0;
function rowTemplate(i, name) {
return `<tr data-index=${i}>
<td>${name}</td>
</tr>`
}
function addRow() {
$('#my-tbody').append(rowTemplate(i, some_name));
i++;
}
Jinja template:
<form name="my-form" method="POST" action="{{ url_for("my_func") }}">
<table name="my-table">
<thead>
</thead>
<tbody id="my-tbody">
</tbody>
</table>
</form>
Flask route:
@app.route("/run", methods=['POST'])
def my_func():
print(request.form)
return render_template("my_template.jinja2")
The request.form seems to not include table and its children elements. I found a suggestion to use a input type=hidden tag and store the info i need there, so I can access it from request.form but it still doesn't show up in request.form if I include it in the javascript function like so:
let i = 0;
function rowTemplate(i, name) {
return `<tr data-index=${i}>
<td>${name}</td>
<input type="hidden" name=${name} value=${i}>
</tr>`
}
The hidden input element shows up in request.form only if I manually add it in the tbody but that doesn't work for me, I need to be adding it from the javascript function
<tbody id="my-tbody">
<input type="hidden" name="test" value="test">
</tbody>
I might have the wrong approach altogether. How do I get the values of the table's td elements to my_func?
Solution 1:[1]
I agree with Christoph that modern javascript frameworks make developing such an application part much easier. However, an approach using input fields should send the data to the server so that it can be queried.
The following simple example may not be quite what you intend and could certainly be implemented better, but it shows you a variant that works. The user can build a table embedded in a form step by step and then send it. In order to finally make the data queryable, the mentioned input fields are used within the table.
from flask import (
Flask,
redirect,
render_template,
request,
url_for
)
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/func', methods=['POST'])
def func():
print(request.form)
return redirect(url_for('index'))
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style media="screen">
table {
width: 100%;
}
tr td:last-child {
width: 10%;
white-space: nowrap
}
tr td:first-child {
padding: 0 0.6rem 0 0;
}
tr td > * {
width: 100%;
}
.block {
display: block;
width: 100%;
}
</style>
</head>
<body>
<form name="my-form" action="{{ url_for('func') }}" method="post">
<table>
<thead>
<tr>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr id="input-row">
<td><input type="text" name="input" tabindex="0" /></td>
<td><button type="submit">Add</button></td>
</tr>
</tbody>
</table>
</form>
<button name="send-btn" class="block">Submit</button>
<script type="text/javascript">
(() => {
const form = document.querySelector('form[name="my-form"]');
form.addEventListener('submit', evt => {
evt.preventDefault();
const name = evt.target.input.value.trim();
if (name.length === 0) return;
const tbody = document.querySelector('tbody');
const tr = document.createElement('tr');
tr.innerHTML = `
<td><input type="text" name="name" value="${name}" tabindex="-1" readonly /></td>
<td><button type="button" class="rm-btn">Remove</button></td>
`;
tbody.insertBefore(tr, tbody.lastElementChild);
const btn = tr.querySelector('.rm-btn')
btn.addEventListener('click', evt => {
evt.target.closest('tr').remove();
});
evt.target.reset();
});
const sendBtn = document.querySelector('button[name=send-btn]');
sendBtn.addEventListener('click', evt => {
form.querySelector('#input-row').remove();
form.submit();
});
})();
</script>
</body>
</html>
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 | Detlef |
