I am trying to create an html table by fetching json from an api, but when it builds the table it takes a long time to populate, not because of the fetch request but because it is building a table with 600-1000 records and I want to speed it up. I don't have much experience with js or html so its super rough code I just want to be able to speed it up. I have seen answers about adding pagination but I am not quite sure how to approach this.
<meta name="viewport" content="width=device-width, initial-scale=1">
<head>
<title>Example</title>
<link rel="stylesheet" href="https://unpkg.com/ag-grid-community/dist/styles/ag-grid.css">
<link rel="stylesheet" href="https://unpkg.com/ag-grid-community/dist/styles/ag-theme-balham.css">
</head>
<body>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/css/bootstrap.min.css"
integrity="sha512-Ez0cGzNzHR1tYAv56860NLspgUGuQw16GiOOp/I2LuTmpSK9xDXlgJz3XN4cnpXWDmkNBKXR/VDMTCnAaEooxA=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<label>
Select a nurse:
<select name="nurses">
<option value="">Select One …</option>
<option value="Om">Om</option>
<option value="Reb">Reb</option>
<option value="Man">Man</option>
<option value="Gus">Gus</option>
</select>
</label>
<div ></div>
<table >
<thead>
<tr>
<th scope="col">Bed</th>
<th scope="col">Patient</th>
<th scope="col">Status</th>
<th scope="col">Assigned Nurse ID</th>
<th scope="col">Need Urgency</th>
<th scope="col">Need</th>
<th scope="col">Nurse</th>
<th scope="col">Req ID</th>
<th scope="col">Time Created Epoch</th>
<th scope="col">Patient ID</th>
<th scope="col">Time</th>
<th scope="col">Room</th>
</tr>
</thead>
<tbody id="tbody">
</tbody>
</table>
<script type="text/javascript" charset="utf-8">
const selectElement = document.querySelector('.nurses');
var x = '';
selectElement.addEventListener('change', (event) => {
const result = document.querySelector('.result');
x = event.target.value;
result.textContent = `You Chose ${event.target.value}`;
getdata(x);
});
const tbody = document.querySelector('#tbody');
const getdata = async () => {
const endpoint = "https://my.api.here/beta?nurse=",
response = await fetch(endpoint x),
data = await response.json(),
Items = data.Items;
tbody.innerHTML = "";
Items.forEach(itemObj => {
let { bed, patient_name, status, assigned_nurse_id, need_urgency, need, assigned_nurse, ID, timestamp_created_epoch, patient_id, timestamp_created, room } = itemObj;
tbody.innerHTML = `<tr>
<td>${bed}</td>
<td>${patient_name}</td>
<td>${status}</td>
<td>${assigned_nurse_id}</td>
<td>${need_urgency}</td>
<td>${need}</td>
<td>${assigned_nurse}</td>
<td>${ID}</td>
<td>${timestamp_created_epoch}</td>
<td>${patient_id}</td>
<td>${timestamp_created}</td>
<td>${room}</td>
</tr>`;
});
const getCellValue = (tr, idx) => tr.children[idx].innerText || tr.children[idx].textContent;
const comparer = (idx, asc) => (a, b) => ((v1, v2) =>
v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
)(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
// do the work...
document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
const table = th.closest('table');
const tbody = table.querySelector('tbody');
Array.from(tbody.querySelectorAll('tr'))
.sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
.forEach(tr => tbody.appendChild(tr));
})));
}
</script>
</body>
</html>
CodePudding user response:
Doing innerHTML is a loop is one way to make your code render slow. Build a string and set that string one time.
const items = data.Items;
const rows = items.map(itemObj => {
let { bed, patient_name, status, assigned_nurse_id, need_urgency, need, assigned_nurse, ID, timestamp_created_epoch, patient_id, timestamp_created, room } = itemObj;
return `<tr>
<td>${bed}</td>
<td>${patient_name}</td>
<td>${status}</td>
<td>${assigned_nurse_id}</td>
<td>${need_urgency}</td>
<td>${need}</td>
<td>${assigned_nurse}</td>
<td>${ID}</td>
<td>${timestamp_created_epoch}</td>
<td>${patient_id}</td>
<td>${timestamp_created}</td>
<td>${room}</td>
</tr>`;
});
tbody.innerHTML = rows.join("");