I have a dynamic form that allows you to add more child records as needed. I'm using the cocoon ruby gem. I got auto-save working on a form using the following code:
<script>
$(document).on('turbolinks:load', function() {
var $form = $('form.autosave');
var saving = false;
function autoSaveForm(actionPath) {
var data = $form.serialize();
console.log("POST: " + actionPath);
var request = new XMLHttpRequest();
request.open('POST', actionPath, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(data);
request.onreadystatechange = function () {
if(request.readyState === XMLHttpRequest.DONE && request.status === 200) {
saving = false;
}
};
}
$form.on('blur', 'input', function() {
if (saving) {
return; // don't do the blur action
}
saving = true;
var actionPath = $form.attr('action');
autoSaveForm(actionPath);
});
});
</script>
The "blur" event is being triggered two times. Here's my console output:
POST: /user/profile VM1717:9
POST: /user/profile VM1717:9
I've updated my code from @samanime's suggestion to add a boolean to prevent the event being triggered 4 times. Now it is only triggered twice. Progress!
It appears the issue is with turbolinks and how I setup my JS.
Add a boolean to track if you're currently saving, and then don't do it again if you are.
var saving = false;
$form.on('blur', function () {
if (saving) {
return; // don't do the blur action
}
saving = true;
// do saving stuff
});
And then you'll need to watch when you're done saving, and then set saving
back to false.
function autoSaveForm(actionPath) {
// other stuff
request.onreadystatechange = function () {
if(request.readyState === XMLHttpRequest.DONE && request.status === 200) {
saving = false;
}
};
}
If you wanted to, you could also take that a step farther and have another boolean (like needsToSave
) which would get marked true if you tried to save while saving, and then immediately start saving the latest stuff as soon as the first saving was done.