$("#get-data").on("click", function() {
const btn = $(this)
const btnHtml = btn.html()
btn.html($('#spinner-html').html())
btn.prop('disabled', true)
setTimeout(() => {
// this is my ajax immitation
// on ajax complete:
btn.html(btnHtml)
btn.prop('disabled', false)
}, 2000)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="spinner-html" style="display: none">
Loading...
</div>
<button id="get-data">Get Data</button>
I want each button that invokes ajax call to some API - being disabled and show spinner until API call complete.
The idea is to have it reusable. I.e. ajax part (represented as setTimeout here should not have any reference to the button clicked.
This works perfectly but I feel that repeating those 6 lines of code for button HTML for each button with ajax is a code duplication that can be avoided.
So I'd like to have it generic and reusable. I have tried this way (and some variations) but it didn't work...
function spinnerClick(b, f) {
const btn = $(b)
const btnHtml = btn.html()
btn.html($('#spinner-html').html())
btn.prop('disabled', true)
f()
btn.html(btnHtml) // this goes immediately
btn.prop('disabled', false)
}
function getData() {
// all ajax stuff here
}
$('#get-data').on('click', function () {
spinnerClick(this, getData)
})
Will appreciate any advice on that. Thanks!
UPD: JS fiddle added
CodePudding user response:
thank you for adding jsfiddle, try this please!
function spinnerClick(b, f) {
const btn = $(b)
const btnHtml = btn.html()
btn.html($('#spinner-html').html())
btn.prop('disabled', true)
f().then(() => {
btn.html(btnHtml)
btn.prop('disabled', false)
});
}
function getData() {
return new Promise((resolve) => {setTimeout(() => {
console.log('hello');
resolve(true);
}, 2000);
})
}
$('#get-data').on('click', function () {
spinnerClick(this, getData)
})
CodePudding user response:
I might be misunderstanding, but why not just send the instance off to a separate function so you can access it when it resolves?
$(function() {
$('button').click(function() {
doAjax($(this));
})
})
function doAjax(btn) {
if (btn.find('span.spinner').length > 0) return console.log('wait, still running');
btn.removeClass('finished').append('<span > * </span>');
setTimeout(function() {
btn.addClass('finished').find('span.spinner').remove()
}, 2000)
}
.finished {
background: green;
color: white;
}
.spinner {
color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Click 1</button>
<button>Click 2</button>
<button>Click 3</button>
