Angular JS Logo

Cookies are designed to be a string, and often contain just one key/value pair, or get serialized into a string delimited by semi-colons or commas.  On one of my sites, I’m updating the system (and re-writing the entire site architecture) to maintain a user’s desired preferences, and wanted a way to store all items in one cookie, as I have 8 different settings that I want to allow people to set.

Below is what I finally settled on.  It’s a cookieService that allows me to inject the service into any controller on my site, and utilize the same getter, setter, and default values (which were necessary in my architecture).  If you don’t need the default values, just comment it out.

cookieService


(function() {
angular
  .module('bcpApp.cookieService')
  .factory('cookieService', cookieService);

  cookieService.$inject = ['$cookies'];

  function cookieService($cookies) {
    return {
      get: get,
      set: set,
      getDefaults: getDefaults
    }

    function get(cookieName) {
      var prefs = $cookies.getObject(cookieName);
      var defaults = getDefaults();
      var cookieObj = Object.assign(defaults,prefs);
      if(cookieObj) {
        return cookieObj;
      } else {
        return {};
      }
    }

    function set(name,value,cookieName,expiration) {
      var currentPrefs = get(cookieName);
      var newPref = {};
      newPref[name] = value;
      var newObj = Object.assign(currentPrefs,newPref);
        $cookies.put(cookieName,JSON.stringify(newObj), {
        expires:expiration
      });
    }

    function getDefaults() {
      var prefTypes = {
      'bibleVersion':'NKJV'
      ,'prayerRite':false// rite ii
      ,'prayerDayTime':true // morning
      ,'prayerAll':false // means only readings by day
      ,'lectionaryType':false // RCL
      ,'lectionaryPrayerType':false // Contemporary
      ,'timezone':'0.0' // GMT
      };
      return prefTypes;
    }
  }
})();

Preference Controller

I set the expiration date in the controller, so that I can modify the controller when needed, rather than the service.


(function () {
angular
  .module('bcpApp.preferences')
  .controller('preferencesCtrl', preferences);

  preferences.$inject = ['$cookies','cookieService'];

  function preferences($cookies,cookieService) {
    var vm = this;
    // cookie expiration
    vm.curdate = new Date();
    vm.curdate.setMonth(vm.curdate.getMonth() + 1);

    vm.setPrefs = setPrefs;
    vm.getPrefs = getPrefs;

    vm.preferences = getPrefs();
    vm.fontSize = $cookies.get("FONTSIZE") ? $cookies.get("FONTSIZE") : "14";
    vm.tzSelected = vm.preferences.timezone;
    vm.bibleVersion = vm.preferences.bibleVersion;

    function getPrefs() {
      return cookieService.get("PREFS");
    } 

    function setPrefs(name,value) {
      cookieService.set(name,value,"PREFS",vm.curdate);
    }
  }
})();

I’m sure I’ll modify the service to be a bit more generic in the future; more than likely, I’ll drop the defaults — or pass a defaultValues object — and add in the ability to read simple key/value string ($cookies.get()), but for now, this allows me to drop the service into any controller on the site and utilize the same cookie values from the object that I’ve set with those values.

Leave a Reply

Your email address will not be published. Required fields are marked *