I’m using JQuery with HTML to create a button that when clicked, loads table rows.
My HTML:
<div >
<button id="btn-load-more">Load More</button>
</div>
<p id="loading" style="display:none"> Loading ... </p>
My js:
$("#btn-load-more").on("click", function (event) {
event.preventDefault();
$("#btn-load-more").prop("disabled", true)
$("#loading").show();
//loading table rows
$("#btn-load-more").prop("disabled", false)
$("#loading").hide();
})
I want my button to be disabled when I click on it, and a “Loading…” text will be displayed.
After loading finishes, I want to enable my button again and hide the “Loading…” text.
Currently, the “Loading…” text is only shown after the rows are loaded and not when the rows are loading(my intent).
Can anyone advice me on what’s wrong with my js? Appreciate it!
Edit: Here is a minimum reproducible example. The Loading p tag is not showing when I click on the button with the provided JS code.
$(document).ready(function (){
$("#my-table-tbody tr").slice(2).hide()
if ($("#my-table-tbody tr:hidden").length == 0){
$("#btn-load-more").hide()
}
$("#btn-load-more").on("click", function (event) {
event.preventDefault();
$("#loading").show();
$("#my-table-tbody tr:hidden").slice(0,2).slideDown("fast", function(){
$("#loading").hide();
})
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<div>
<table id="my-table">
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
</tbody>
</table>
<button id="btn-load-more" style="cursor: pointer">Load More</button>
<p id="loading" style="text-align:center; display:none"> Loading ... </p>
</div>
CodePudding user response:
This depends on what this "line of code" actually does:
//loading table rows
If this is a synchronous operation (such as building a bunch of HTML from data you already have) then there isn't much you can do. JavaScript is single-threaded, so this process:
- Change the UI to "loading"
- Perform synchronous, CPU-intensive operation
- Change the UI to "not loading"
This will result in no visual appearance of the first UI update, because the thread is busy performing all of the other operations and then processing the second UI update. So by the time the screen re-draws, only the latest UI is seen.
However, if "loading table rows" is an asynchronous process (such as fetching data via AJAX), then you certainly can temporarily show something in the UI. In this case it depends on how you structure that asynchronous operation.
Since nothing here is async
then I assume we're not using async
and await
. The use of jQuery here suggests a callback-based structure. In that case the second UI update would just need to go in that callback.
For example, if we substitute your asynchronous operation with something simple like setTimeout
just to demonstrate, we see how we can put that code in the callback:
$("#btn-load-more").on("click", function (event) {
event.preventDefault();
// 1: Show the loader
$("#btn-load-more").prop("disabled", true)
$("#loading").show();
// 2: Invoke the asynchronous operation, whatever it may be
setTimeout(function () {
// 3: Hide the loader
$("#btn-load-more").prop("disabled", false)
$("#loading").hide();
}, 3000);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<button id="btn-load-more">Load More</button>
</div>
<p id="loading" style="display:none"> Loading ... </p>
Here we see that the "Loading" state is displayed for 3 seconds and then removed. Whatever your asynchronous operation is, you'd essentially structure the code as:
- Change the UI to "loading"
- Invoke the asynchronous operation
- In the calllback, change the UI to "not loading"