Skip to content

Instantly share code, notes, and snippets.

@danielfriis
Last active April 17, 2023 06:59
Show Gist options
  • Save danielfriis/ba7db29c590c47d32afc279a9bf40f35 to your computer and use it in GitHub Desktop.
Save danielfriis/ba7db29c590c47d32afc279a9bf40f35 to your computer and use it in GitHub Desktop.
Autosave using Stimulus and Rails 7
// app/javascript/controllers/autosave_controller.js
import { Controller } from "@hotwired/stimulus";
import debounce from "lodash.debounce";
// Connects to data-controller="autosave"
export default class extends Controller {
connect() {
this.form = this.element.closest("form");
this.formData = new FormData(this.form);
this.url = this.form.action;
// Get the autosave delay from the data-autosave-delay attribute on the form.
const autosave_delay = this.form.dataset.autosaveDelay;
this.autosaveDelayAsInt = parseInt(autosave_delay);
const requestToDelay = () => this.sendRequest(this.url, this.formData);
// Debounce the request to avoid sending too many requests.
// The request will be sent after the time specified in autosave_target
// has passed since the last call to the debounced function.
this.debouncedRequest = debounce(requestToDelay, this.autosaveDelayAsInt);
}
save() {
this.formData = new FormData(this.form);
// Call the debounced request with the new form data.
this.debouncedRequest(this.url, this.formData);
}
sendRequest(url, formData) {
console.log("Sending request to " + url);
// fetch and trigger turbo_stream response
fetch(url, {
method: "POST",
body: formData,
headers: {
"X-CSRF-Token": document.querySelector("meta[name='csrf-token']").content,
Accept: "text/vnd.turbo-stream.html",
},
credentials: "same-origin",
}).then((response) => {
response.text().then((html) => {
document.body.insertAdjacentHTML("beforeend", html);
});
});
}
}
<%= form_with(model: @my_model, data: {controller: 'autosave', autosave_delay: '1000'}) do |f| %>
<%= f.text_field :title, data: {action: "keyup->autosave#save blur->autosave#save"} %>
<% end %>
# config/importmap.rb
pin "lodash.debounce", to: "https://ga.jspm.io/npm:lodash.debounce@4.0.8/index.js"
// app/javascript/controllers/index.js
import { application } from "./application"
import AutosaveController from "./autosave_controller"
application.register("autosave", AutosaveController)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment