Welcome to @phaqui/autosaver

Watch your text inputs and textareas, and trigger a function on inactivty, or after a period of longer, continous activity.

Installing

npm i -D @phaqui/autosaver

Basic use

Instantiate the autosaver, specifying the function to call as the 'save_fn'. Also demonstrated here are setting custom times in milliseconds for when to consider inactivity (save_after) and non-stop-activity (save_every). These default to six 6 and 30 seconds, respectively.

<script lang="ts">
    import autosaver from "@phaqui/autosaver";

    let text = "";

    const autosaver_opts = {
        save_fn: save,
        save_after: 1*1000,
        save_every: 3*1000,
    }
    const { autosave, dirty, last_saved } = autosaver(autosaver_opts);

    async function save() {
        console.log("saving now");

        // Notice: return true to indicate that the save was successful,
        // so the $dirty and $last_saved stores reflects that
        return true;
    }
</script>

<p>dirty? {$dirty}</p>
<p>last saved: {$last_saved}</p>
<input bind:value={text} use:autosave>
        

Dirty? false

Last saved: Sun Mar 20 2022 22:30:07 GMT+0100 (Central European Standard Time)

Watch multiple elements at the same time

The action can be applied to multiple elements, and will track them all, calling the save method when any of them are changed.

<script lang="ts">
    import autosaver from "@phaqui/autosaver";

    let firstname = "", lastname = "";

    const autosaver_opts = {
        save_fn: save,
        save_after: 1*1000,
        save_every: 3*1000,
    }
    const { autosave, dirty } = autosaver(autosaver);

    async function save() {
        console.log("saving now");
        return true;
    }
</script>

<p>dirty? {$dirty}</p>
<p>last saved: {$last_saved}</p>
<input bind:value={firstname} use:autosave>
<input bind:value={lastname} use:autosave>
        

Dirty? false

Which fields changed?

If the element has no 'name' attribute, and no custom name is set in the action params, the autosaver will not track which elements are dirty, and just call the save_fn without any arguments.

However, if the element has a name attribute (or a "name" is given in the params to the action, then save_fn will be called with a set containing the names of the elements that was changed.
Note: Passing the name in the action param will take presence over the name set as an attribute, if both are found.

<script lang="ts">
    import autosaver from "@phaqui/autosaver";

    let firstname = "", lastname = "";

    const autosaver_opts = {
        save_fn: save,
        save_after: 1*1000,
        save_every: 3*1000,
    }
    const { autosave, dirty } = autosaver(autosaver);

    async function save(dirty_fields: Set<string>) {
        console.log("saving now, dirty fields:", dirty_fields);
        return true;
    }
</script>

<p>dirty? {$dirty}</p>
<input name="firstname" bind:value={firstname} use:autosave>
<input name="lastname" bind:value={lastname} use:autosave={{ name: "overridden-name" }}>
        

Dirty? false

Save manually

Whenever you need to issue a save manually, use the provided save_manually function instead of calling your save_fn directly, so that the dirty- and last_saved stores are updated.

<script lang="ts">
    import autosaver from "@phaqui/autosaver";

    let firstname = "", lastname = "";

    // Notice: For this example, using default times
    // (saves after 6s of inactivity, save every 30s of activity)
    const autosaver_opts = { save_fn: save };
    const { autosave, dirty, save_manually } = autosaver(autosaver);

    async function save(dirty_fields: Set<string>) {
        console.log("saving now, dirty fields:", dirty_fields);
        return true;
    }
</script>

<p>dirty? {$dirty}</p>
<input name="firstname" bind:value={firstname} use:autosave>
<input name="lastname" bind:value={lastname} use:autosave={{ name: "overridden-name" }}>
<button on:click={save_manually}>save now</button>
        

Dirty? false