Reflecting web app settings in URL hash

As I have been experiencing with web apps I got a need to reflect the settings in the URL. I needed a way to store the state of the web app over time and to make it possibel for the users of the web app to it with others or simply bookmark it (The webapp: “CSS3 image manipulation“). It has become a trend to let web apps to have such features, for instance Lea Verou is a master of web apps and her web apps are handling this very well.

Take a look at

  1. Cubic-bezier http://cubic-bezier.com/#.17,.67,.83,.67
  2. CSS Patterns Gallery (zig-zag) http://lea.verou.me/css3patterns/#zig-zag

My setup – AngularJS based web app

I am no javascript ninja, even if I am no novice, so it took me some time to find thecode parts which would fit the needs my web app had to be able to store states in the URL.I ended up with a hash based soloution. Reading a blog post about HTML 5 History opened my eyes to a simple way to handle a hash based soloution.

My QueryStringSettings javascript module

I created a simple “QueryString javascript module” (16 lines of javascript) which has 1 property and 2 methodes, pretty lightweight.

qs.selector The CSS selector for retriving settings (Default: [ng-model]:not([type=”checkbox”]))

qs.get() Methode to set settings from URL hash

qs.set() Methode to set URL hash from web app set settings

It needs a selector which matches the elements which are the web app settings. The default value matches elements which are ng-model in the AngularJS webapp API, which I often use for my web apps. You can use any selector for elements which must have an ID and a value attribute (normally it is FORM elements). I in my default selector filter out checkboxes as I do not use them as actual settings.

QueryStringSettings – The code on Gist.github.com

You may download the code at Gist

  1. You may want to use your own selector:QueryStringSettings.selector = ’input’
  2. A callback has been added:QueryStringSettings.doneCallbackwhich can be set to your own function.
    • For instance to log the activity to the Console:
      QueryStringSettings.doneCallback = function() {
        console.log(arguments);
      }
    • Get returns: [“get”, array of found settings – key/value]
    • Set returns: [“set”, array of settings stored in URL hash – key/value]
  3. The code needs to be initialized setting the values of the web app settings:QueryStringSettings.get()
  4. Every time changes happen to “settings” you should update the URLQueryStringSettings.set([scope]) // The scope is optional for use with AngularJS

That is it! You will need to place the code a place after the HTML elements have been loaded (perhaps just above </body>).

Using it together with AngularJS

If you as me want to use it together with AnguarJS you will observe that even if AngularJS says it will always reflect any changes to its ng-models in the web app scope, it does not work when you in a “dirty” way update HTML elements which are models. Therefore you will need to do something extra.

Setting the passed settings from URL hash to Scope model

In the end of of your Model simply add:

QueryStringSettings.get($scope);

To get the settings from URL hash into your scope models.

Also to ensure that changes are reflected in the URL hash part you will need to have the QueryStringSettings.set() placed somewhere within your model.Actually for now I am using a very “wet” solution, so if you have a “dry” solution please write a comment with it!

A “wet” solution for updating URL hash when using QueryStringSettings with AngularJS
QueryStringSettings.get($scope);
  window.setInterval(function() {
  QueryStringSettings.set();
}, 2000);

Update: Found a more “Dry” solution for AngularJS integration

$scope.$watch(function() {
    var z = '';
    for(prop in $scope) {
      z+=(typeof $scope[prop]!=='function') ? $scope[prop] : '';
    };
    return z;
 }, function() {
    QueryStringSettings.set();
});
Examples of my use

After I have added this functionality it is now possible for users of my CSS image manipulation webapp to share their styles. Here are some examples:

Update 2012-11-20
Finally! It is dry now as I read a blog post by Peter TerkildsenAngularJS tips and tricks“.
I needed to use the $apply() on the “globalscope” like this:
QueryStringSettings.get($scope);
$scopeGlobal.$apply();
US

Leave a Reply