Skip to content

Instantly share code, notes, and snippets.

@andreasvirkus
Created January 16, 2021 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreasvirkus/4f1c8b0b8e0bc0e36305417dbd0f6047 to your computer and use it in GitHub Desktop.
Save andreasvirkus/4f1c8b0b8e0bc0e36305417dbd0f6047 to your computer and use it in GitHub Desktop.
import Vue from "vue";
function setupWatchers(data = []) {
if (!(this instanceof Vue)) throw new Error("Persistence plugin needs to be called from a Vue component");
if (!data) return;
const query = new URLSearchParams(location.search);
data.forEach((name) => {
const key = `${this.$options.name}_${name}`;
if (query.has(key)) this[name] = JSON.parse(query.get(key));
this.$watch(name, (val) => serializeToStorage(key, val));
});
}
/**
* Appends or deletes filter param in query string
*/
const serializeToStorage = (key, val) => {
const query = new URLSearchParams(location.search);
// TODO: Best way to check if val is empty? Should we also remove 0?
// Another option is to store the default/initial value per key and delete from query if initial
if (val) {
if (query.has(key)) query.set(key, JSON.stringify(val));
else query.append(key, JSON.stringify(val));
} else {
query.delete(key);
}
const addQuery = !![...query.keys()].length;
history.replaceState(null, "", `${location.pathname}${addQuery ? "?" : ""}${query}`);
};
/**
* Vue plugin that sets up watchers for provided data properties and syncs them to the URI's query string
*
* TODO: Decide how to scope values in query (e.g. component name can be repeated as well)
* TODO: Decide how to handle data model changes
* TODO: Look into ways to shorten the URL (last resort could even be a small self-hosted tinyurl service)
*/
export default function (Vue) {
Vue.prototype.$persist = setupWatchers;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment