Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJs reflect changes in current browser tab to other tab

Tags:

angularjs

Using this code, does angularjs supports binding that will also reflects the changes in the current tab you're working with into the other tab

<input type="text" ng-model="name"><span ng-bind="name"></span>
like image 961
user2572094 Avatar asked May 26 '26 06:05

user2572094


1 Answers

No, not using just that code.

However, I just wrote a nice directive for you to use with ng-model and ng-bind (does not work with just {{ inline expressions }}, though).

Here it is in action

And here is the code:

/**
 * sync-between-tabs directive.
 * Use in conjunction with ng-model or ng-bind to synchronise the contents
 * between tabs. The value is synced using localStorage, so each thing to sync
 * needs a unique key. Specify the key using the sync-between-tabs attribute
 * value, or leave blank to use the ng-model or ng-bind attributes.
 * Example usage:
 *    <input ng-model="some.thing" sync-between-tabs></input>
 *         uses the key "some.thing"
 *    <input ng-model="some.thing" sync-between-tabs="UNIQUEKEY25"></input>
 *         uses the key "UNIQUEKEY25"
 *    <span ng-bind="some.other.thing" sync-between-tabs></span>
 *         uses the key "some.other.thing"
 *    <span ng-bind="name" sync-between-tabs="UNIQUE_KEY_12"></span>
 *         uses the key "UNIQUE_KEY_12"
 */
app.directive('syncBetweenTabs', ['$window', '$parse',
  function($window, $parse) {
    var callbacks = {}, keysToWatch = [];
    var localStorage = {
      key: function(key) {
        return '__syncValue_' + (key || '').replace('__syncValue_', '');
      },
      getItem: function(key) {
        return $window.localStorage.getItem(localStorage.key(key));
      },
      setItem: function(key, val) {
        $window.localStorage.setItem(localStorage.key(key), val);
      },
      onItemChange: function(key, callback) {
        key = localStorage.key(key);
        var keyAlreadyExists = false;
        if (keysToWatch.indexOf(key) < 0) {
          keysToWatch.push(key);
          callbacks[key] = [callback];
        } else {
          callbacks[key].push(callback);
          keyAlreadyExists = true;
        }
        return function deregister() {
          if (!keyAlreadyExists)
            keysToWatch = without(keysToWatch, key);
          callbacks[key] = without(callbacks[key], callback);
          if (callbacks.length === 0)
            delete callbacks[key];
        };
      }
    };

    function without(arr, value) {
      var newArr = [];
      for (var i = 0, len = arr.length; i < len; ++i) {
        if (arr[i] !== value)
          newArr.push(arr[i]);
      }
      return newArr;
    }

    if ($window.addEventListener) {
      $window.addEventListener("storage", handle_storage, false);
    } else {
      $window.attachEvent("onstorage", handle_storage);
    }

    function handle_storage(e) {
      if (!e) e = $window.event;
      if (callbacks[e.key])
        angular.forEach(callbacks[e.key], function(callback) {
          callback(e.newValue);
        });
    }

    return {
      restrict: 'A',
      require: '?ngModel',
      link: function(scope, elem, attrs, ngModelCtrl) {
        var key = attrs['syncBetweenTabs'],
          mode = 'unknown',
          dereg, ngBindExpr
        if (ngModelCtrl) {
          mode = 'ngModel';
          if (!key)
            key = attrs['ngModel'];
        } else if (attrs['ngBind']) {
          mode = 'ngBind';
          if (!key)
            key = attrs['ngBind'];
        } else {
          throw new Error('sync-between-tabs only works for ng-model and ng-bind at present');
        }
        if (mode == 'ngModel') {
          ngModelCtrl.$viewChangeListeners.push(function() {
            localStorage.setItem(key, ngModelCtrl.$viewValue);
          });
          var currentValue = localStorage.getItem(key);
          if (currentValue && currentValue !== ngModelCtrl.$viewValue) {
            ngModelCtrl.$setViewValue(currentValue);
            ngModelCtrl.$render();
          }
          dereg = localStorage.onItemChange(key, function(value) {
            ngModelCtrl.$setViewValue(value);
            ngModelCtrl.$render();
          });
        } else {
          ngBindExpr = $parse(attrs['ngBind']);
          dereg = localStorage.onItemChange(key, function(value) {
            ngBindExpr.assign(scope, value);
            scope.$digest();
          });
        }
        scope.$on('$destroy', dereg);
      }
    }
  }
]);
like image 192
GregL Avatar answered May 30 '26 12:05

GregL