AngularJs reflects changes in current browser tab to another tab

Using this code, does angularjs support bindings that will also reflect the changes of the current tab you are working with to another tab

<input type="text" ng-model="name"><span ng-bind="name"></span>

      

+3


source to share


2 answers


No, not using just this code.

However, I just wrote a nice directive to use with ng-model

and ng-bind

(although this doesn't only work with {{ inline expressions }}

).

Here he is in action



And here's 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);
      }
    }
  }
]);

      

+4


source


Assuming both tabs have the same site loaded on the same domain, you can use local / session storage or cookies to publish shared data and make it available to any tab, but instead, you have to constantly check for changes. but it should work



+1


source







All Articles