npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-preferences

v3.0.0

Published

The coolest and easiest way to manage your user's preferences through localStorage and no back-end calls at all.

Downloads

5,072

Readme

Vue Preferences

Motivation

Many times happens that you want to handle some persistent state on your application but you find that doing an actual call to your back-end is like "killing a mosquito with a bazooka". For those scenarios, we decided to create the vue-preferences library.

With vue-preferences, you can keep some state of your app on the client side by using any storage strategy you find suitable, as a default we use window.localStorage under the hood. This way you ensure your UX keeps consistent while at the same time avoiding simple but annoying calls to your back-end. You can set some user preferences such as theme color, users' default, hidden elements (after user opted-in), table sorting, and many others you can imagine with great simplicity.

Table of content

Installation

If you prefer yarn:

$ yarn add vue-preferences --save

or with npm:

$ npm install vue-preferences --save

Usage

You can define your vue-preferences in many ways. You can create them one by one, many at once and also with or without default values. Let's see what this means!

But first, remember to install the plugin before using it with:

import VuePreferences from 'vue-preferences';

Vue.use(VuePreferences);

new Vue({
  render: h => h(App),
}).$mount('#app');

This only needs to be done once, in the main.js or index.js file of your app, where you mount the Vue app for the first time.

Declaring vue-preferences

Single preference at a time

Here you'll see how to create a single preference at a time.

Basically, you would do something like:

  import { preference } from 'vue-preferences'

  computed: {
    isDarkMode: preference('isDarkModeEnabled', { defaultValue: false, reactive: false })
  }

keep in mind that there is no need to pass an options object if you don't need it

  computed: {
    isDarkMode: preference('isDarkModeEnabled')
  }

This will basically map your computed property isDarkMode to the value you have stored in localStorage under the key isDarkModeEnabled. Here you are explicitly mapping the localStorage key isDarkModeEnabled (that we will be creating for you) with your isDarkMode computed property.

Multiple preferences at the same time

We have two possible ways to create multiple vue-preferences properties at a time: the Array way or the Object way.

The Array way

Suppose you want to create two properties translatedTo and isZoomed. In the Array way, you could achieve that by doing:

  import { mapPreferences } from 'vue-preferences'

  computed: {
    ...mapPreferences(["translatedTo", "isZoomed"])
  }

Does it sound natural to you?

If it does, it's because it's just like vuex! 🎉

For those who don't know what I'm talking about, I will explain:

  ...mapPreferences(["translatedTo", "isZoomed"])

is great because you can declare as many preferences as you need with just one single line and internally this is just the same as doing:

  translatedTo: preference('translatedTo'),
  isZoomed: preference('isZoomed')

Does it make more sense now? - Cool!

Hang on, but... Is there a way to pass my custom options to each preference if I declare them as an array?

- I'm sorry, you can't. You can't provide custom options to each preference, but we have good news! We also added support to the Object way, remember we had mentioned this before. Let's see how to use it.

The Object way

By using the Object way you are allowed to create both multiple preferences and also provide custom options to each preference (such as defaultValue) at the same time.

Let's see how to do it:

  computed: {
    ...mapPreferences({
      translatedTo: {
        defaultValue: 'spanish'
      },
      isZoomed: {
        defaultValue: false
      }
    })
  }

Programmatic usage

This might look pretty familiar to you if you are used to window.localStorage API. But it has some advantages to it, for example, you create the property and you only need to know the name once, after that you can just pass the preference as a variable and use it with get/set.

Retrieve data

If at some point you need to know what is in your preference property, you just need to call the get method and you will have it.

// suppose you defined the following preference for saving the site's locale
const locale = preference('locale', { defaultValue: 'en' });

// obtains the value stored in the storage (by default localStorage) under the key "locale" or returns default: "en"
console.log('Current locale is:', locale.get());

// prints "Current locale is: en"

Keep in mind that if you defined your preference without a default value, and you haven't called the API to set any it, then the result of calling get will be null.

Store data

If you didn't define the preference as a computed property and instead did it as a regular variable, then it might happen that you want to handle it by your own.

If that's the case, you don't have other alternative than using the API to set the new values (in fact you have another alternative: to change the storage values with its API, but why would you do that? 🤭)

How to do it?

// suppose the same property than in the previous example
const locale = preference('locale', { defaultValue: 'en' });

locale.set('es');

// obtains the value stored in the storage (by default localStorage) under the key "locale" or returns default: "en"
console.log('Current locale is:', locale.get());

// prints "Current locale is: es"

This time the result is es, not en.

Options

This are the options available for the properties you define, any option you define on a preference has precedence over any global option you have defined or any provided default.

| Option | Default Value | Description | | ------------- | ------------- | ------------- | | storage | window.localStorage | Allows you to set up where the properties will be saved. By default we use localStorage, but you can use for example sessionStorage or any kind of storage. If you provide an object that has the same getItem and setItem API that localStorage has, then you can use that as a storage. | | defaultValue | null | Allows you to set up the preference with a custom default value. This allows you to ensure that even the first time the preference is read you will get something. | | reactive | true | By default preferences are reactive. This means that if you use the property in your template/code you can expect it to be observed and trigger re-renders, just like normal computed properties while at the same time the values get persisted to localStorage (or your storage of choice). If you disable this behavior the property will not trigger re-renders/re-computation of dependant code | | serializer | JSON.stringify | The default serializer is JSON.stringify, this allows you to save all kinds of objects. You could for example use a CSV serializer.| | deserializer | JSON.parse | The default deserializer is JSON.parse, and if it cannot deserialize a value it will return the value raw from the storage.| | namespace | '' | The default namespace is empty, which means that the properties will get saved and read from the storage with the name of the preference. For example of the preference name is firstName, it will get stored as firstName, but if you add the namespace userData, it will get saved as userData:firstName| | ttl | infinite | The Time-to-Live of a preference, the time in seconds after the preference creation/update at which a preference - if found on the storage - will be ignored and destroyed when tried to be read.| | expiration | infinite | A Date or function (returning a Date) at which the preference will be considered expired. This behaves like the ttl option.|

🚀 In the future, we will be supporting other custom options that will add even more power to the preferences you set. Stay tuned and support!

Global library options

Options can be defined globally and will affect all the preferences in your project unless overridden by individual preferences.

Example of global options usage:

import VuePreferences from 'vue-preferences';

Vue.use(VuePreferences, {
  storage: window.sessionStorage,
  namespace: 'my-app'
});

Notes

⚡ Please note that the API for defining multiple preferences at the same time is different from the one for creating a single preference (preference vs ...mapPreferences) ⚡

Contributing

All contributions or issue reporting are welcomed. If you are submitting a bug issue please include information to help us debug it!

If you plan to contribute, please make sure you test the code. Any new feature or bug fix should have its own test case.

Credits