I can not figure out why data is not binding and loading the handsontable. The user would enter in course number and section, and click display grades button. A fetch would retrieve the data from an sqlite database and return the rows from the database query. According to handsontable i must send loadData an array of arrays.
When I run the app I get these 4 print statements
update student grades for course
<class 'list'> [{'stg_st_number': 1111, 'stg_crs_number': 'MAT101', 'stg_crs_section': 'B', 'stg_st_semester': '2023X', 'stg_g1': 80, 'stg_g2': 75, 'stg_g3': 71, 'stg_g4': None, 'stg_g5': None, 'stg_g6': None, 'stg_g7': None, 'stg_g8': None, 'stg_g9': None, 'stg_g10': None, 'stg_final': None}, {'stg_st_number': 2222, 'stg_crs_number': 'MAT101', 'stg_crs_section': 'B', 'stg_st_semester': '2023X', 'stg_g1': 81, 'stg_g2': 76, 'stg_g3': 72, 'stg_g4': 74, 'stg_g5': 75, 'stg_g6': 76, 'stg_g7': 77, 'stg_g8': 78, 'stg_g9': 79, 'stg_g10': 80, 'stg_final': None}]
<class 'list'> [[1111, 'MAT101', 'B', '2023X', 80, 75, 71, None, None, None, None, None, None, None, None], [2222, 'MAT101', 'B', '2023X', 81, 76, 72, 74, 75, 76, 77, 78, 79, 80, None]]
<class 'flask.wrappers.Response'> <Response 305 bytes [200 OK]>
And the browser console shows I’m passing an array of arrays
- (2) [Array(15), Array(15)]
- 0: Array(15)
- 0: 1111
- 1: "MAT101"
- 2: "B"
- 3: "2023X"
- 4: 80
- 5: 75
- 6: 71
- 7: null
- 8: null
- 9: null
- 10: null
- 11: null
- 12: null
- 13: null
- 14: null
- length: 15
- [[Prototype]]: Array(0)
- 1: (15) [2222, 'MAT101', 'B', '2023X', 81, 76, 72, 74, 75, 76, 77, 78, 79, 80, null]
- length: 2
- [[Prototype]]: Array(0)
I can not figure out why data is not binding and loading. I get a empty default handsontable with header rows. I thought it might be a timing issue because it says undefinded. So I read in another answer to place a ? on this line of code to make sure the data is there before trying to access it.
let mydata = response.data?.map( data => (
[data.stg_st_number, data.stg_g1, data.stg_g2, data.stg_g3, data.stg_g4, data.stg_g5
, data.stg_g6, data.stg_g7, data.stg_g8, data.stg_g9, data.stg_g10, data.stg_final]
))
Possible I'm not really returning an array of arrays?
thanks in advance
handsontable.full.min.js:920 Uncaught (in promise) Error: loadData only accepts array of objects or array of arrays (undefined given) at t.replaceData (handsontable.full.min.js:920:123400) at t.default.loadData (handsontable.full.min.js:920:70714) at guestbook:75:13 I have included a small main.py program with 4 print statements to show the issue and a small html file with JavaScript
main.py
import sqlite3
import os
app = Flask(__name__)
# Connect to the SQLite database.
chk_db_path = os.environ.get('SYSTEMDRIVE') + os.environ.get('HOMEPATH') + '\\PycharmProjects\\10\\chk\\chk.db'
print('chk_db_path = ', chk_db_path)
con = sqlite3.connect(chk_db_path, check_same_thread=False)
con.row_factory = sqlite3.Row
@app.route('/guestbook')
def guestbook():
return render_template('guestbook.html')
@app.route('/guestbook/create_entry', methods=['POST'])
def create_entry():
print("in create")
# get input form fields course number and section, in json format, from web page using fetch api
req = request.get_json()
print(req['coursenumber'], req['section'])
# query st_grades for all students in that course number,section, semester
sm = con.execute('''Select sm_year||sm_semester from semester where sm_status = :status''', {'status': "Active"}).fetchone()
for current_semester in sm:
get_crs_grade = con.execute('''SELECT * FROM st_grades WHERE stg_crs_number = :crs_number
AND stg_crs_section = :crs_section
AND stg_st_semester = :sm''',
{'crs_number': req['coursenumber'],'crs_section': req['section'], 'sm': current_semester})
crs_grade = get_crs_grade.fetchall()
print('update student grades for course')
list_comp_version = [{k: item[k] for k in item.keys()} for item in crs_grade]
print(type(list_comp_version), list_comp_version)
# Convert the list of dictionaries into an array of arrays.
array_of_arrays = [[element for element in dictionary.values()] for dictionary in list_comp_version]
print(type(array_of_arrays), array_of_arrays)
res = make_response(jsonify(array_of_arrays), 200)
print(type(res), res)
# res = make_response(jsonify(req), 200)
return res
if __name__ == '__main__':
app.run(debug=True)
guestbook.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Guestbook</title>
<link type="text/css" rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/handsontable.full.min.css"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col">
<h1> Instructor Grades Update</h1>
<hr>
<div class="mb3">
<div class="form-group">
<label>Course Number</label>
<input type="text" class="form-control" id="coursenumber" placeholder="Enter course number">
</div>
<div class="form-group">
<label>Section</label>
<input type="text" class="form-control" id="section" placeholder="Enter section letter">
</div>
<button type="button" class="btn btn-primary"
style="margin-right: 30px; margin-top: 30px; margin-bottom 30px" onclick="submit_entry();">
Display Grades
</button>
</div>
</div>
</div>
<div class="ht"></div>
</div>
<script>
function submit_entry(){
const ht = document.querySelector('.ht');
let hot;
var coursenumber = document.getElementById("coursenumber");
var section = document.getElementById("section");
var entry = {
coursenumber: coursenumber.value,
section: section.value
};
hot = new Handsontable(ht, {
colHeaders: ['Student Number', 'Grade 1', 'Grade 2', 'Grade 3', 'Grade 4', 'Grade 5', 'Grade 6',
'Grade 7', 'Grade 8', 'Grade 9', 'Grade 10', 'Final Grade'],
rowHeaders: true,
licenseKey: 'non-commercial-and-evaluation'
})
fetch(`${window.origin}/guestbook/create_entry`, {
method: "POST",
credentials: "include",
body: JSON.stringify(entry),
cache: "no-cache",
headers: new Headers({
"content-type": "application/json"
})
})
.then(function(response){
if (response.status !== 200){
console.log(`Response status was not 200: ${response.status}`);
return;
}
response.json().then(function(data){
console.log(data);
let mydata = response.data?.map( data => (
[data.stg_st_number, data.stg_g1, data.stg_g2, data.stg_g3, data.stg_g4, data.stg_g5
, data.stg_g6, data.stg_g7, data.stg_g8, data.stg_g9, data.stg_g10, data.stg_final]
))
hot.loadData(mydata)
})
})
}
</script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous"></script>
</body>
</html>