AngularJs reflects changes in current browser tab to another tab
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 }}
).
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 to share