I want to reload the pages of a particular site on all the open tabs when the value in the local Storage changes. How can I achieve this?
You can subscribe to storage events like this:
window.addEventListener('storage', function(e) {
// Some storage value changed. Reload tab!
});
As noted in the linked documentation:
The storage event of the Window interface fires when a storage area (localStorage or sessionStorage) has been modified in the context of another document.
Do note this is limited to tabs which have access to the same local storage (limited by the domain of the website).
Here is a solution to refresh all using the same Angular Application
Step 1: Make a list of all Opened Tabs With a unique ID.
const myTab = sessionStorage.tabID ? sessionStorage.tabID: Math.random();
let tabList = JSON.parse(localStorage.getItem('tabList'));
if(!tabList) tabList = {};
tabList[myTab] = { refresh: false, updated_ts: new Date() };
localStorage.setItem('tabList', JSON.stringify(tabList));
Step 2: Monitor Activity in local storage. [This can be done in a number of ways]
setInterval(function(){
let tabList = JSON.parse(localStorage.getItem('tabList'));
if(tabList && tabList[myTab] && tabList[myTab].refresh){
delete tabList[myTab];
localStorage.setItem('tabList', JSON.stringify(tabList));
console.log("Do refesh");
// location.reload();
}
else{
console.log("Don't refesh");
}
}, 3000);
OR (Subscribe to storage events)
window.addEventListener('storage', function(e) {
// Your logic
});
Step 3: Trigger Refresh
function triggerRefesh() {
let tabList = JSON.parse(localStorage.getItem('tabList'));
if(tabList) for (const tabID in tabList) tabList[tabID].refesh = true;
localStorage.setItem('tabList', JSON.stringify(tabList));
}
Note: You should not reload an angular application, rather route to your authentication page or refresh your component
Related
Recently just started building a PWA and I thought a useful feature for privacy and control could be a toggle on the site that allows the user to force the site to remain in offline mode until the toggle is pressed again. After some research, however, I am unable to find any way to accomplish this, anybody has any ideas? Thanks in advance.
Create a toggle or checkbox on in the HTML from where you will control the state. This input element will control wether offline mode is on or off. The value of that input has to be send to the service worker who then can decide what to do whenever a fetch request is being made.
<input id="check-offline" type="checkbox" name="offline-mode">
<label for="check-offline">Offline mode</label>
In your main thread select the button and register your Service Worker. Whenever the worker has registered successfully add an event listener to the input you've created up here and listen for a change. In the handler of the event listener use the postMessage function on the worker to send the checked value to the worker.
const offLineToggle = document.getElementById('check-offline');
navigator.serviceWorker.register('/path/to/service-worker.js').then(registration => {
const serviceWorker = registration.active;
if (serviceWorker !== null) {
offLineToggle.addEventListener('change', event => {
serviceWorker.postMessage({
name: 'offlineMode',
value: event.target.checked
});
});
}
});
Then in your Service Worker script create an object (or variable) to store the current settings in. In the ServiceWorkerGlobalScope listen for the message event. This is the receiving end for the postMessage function. Here you can handle the data and update the settings for the offlineMode.
Then add another event listener and listen for the fetch event, which will be fired whenever a fetch request has been made from the main thread. In the event handler check if the offline mode is on or off and handle accordingly.
const settings = {
offlineMode: false
};
self.addEventListener('message', { data } => {
const { name, value } = data;
if (settings.hasOwnProperty(name)) {
settings[name] = value;
}
});
self.addEventListener('fetch', event => {
const { offlineMode } = settings;
if (offlineMode === true) {
// Force return data from cache.
} else {
// Get fresh data from the server.
}
});
This all is an outline of how it could work. Read up on the Using Service Workers article on MDN to see how you can access the cache and control the data that is being send to the client.
Service workers have access to indexedDB. Alternatively, DOM has access to the cache storage.
You could cache a key "offline" either in indexedDB or cache storage, and check the value on the fetch event.
Once the user is logged in, am maintaining user token in local storage and its is available across all the tabs and once the user close the window, I need to remove the user token from the local storage.
How can I remove local storage when the browser/window/Tab is closed?
Found this tip somewhere a while ago. You can store your data to localStorage for a couple of seconds and add an event listener for a storage event. By doing this, you will know when any of the tabs wrote something to your localStorage and you can copy its content to the sessionStorage, then just clear the localStorage afterwards
Got It!
Just I added the below code in app.component.ts file to remove all local storage data when the window is closed.
import { HostListener } from '#angular/core';
#HostListener('window:beforeunload', ['$event'])
public beforeunloadHandler($event) {
localStorage.removeItem('UserToken');
}
window.addEventListener("unload", function(event) {
//Use any of local storage methods to remove the user.
localStorage.removeItem('key'); // key you want to be removed.
//OR
localStorage.clear();
});
// You can also try using.
window.addEventListener("unload", function(event) { localStorage.removeItem('key'); });
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onunload
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
I use method addEventListener with storage parameter to detect changing of storage. However, it didn't work. I do it on Chrome. What is wrong?
window.addEventListener('storage', function(storageEvent){
console.log(storageEvent);
});
function setData(){
localStorage.setItem('superpower', 'heatvision');
}
function clearData(){
localStorage.clear()
}
<button onClick="setData()">Set</button>
<button onClick="clearData()">Clear</button>
It's impossible to detect storage changes in the same window like that. Since you're using getItem and setItem, just try using a wrapper method, and calling that wrapper method instead:
const myLSInterface = {
listeners: [],
set: function(key, value) {
localStorage.key = value;
const thisEventObj = { key, value };
this.listeners.forEach(listener => listener(thisEventObj));
},
addListener: function(listener) {
this.listeners.push(listener);
},
};
myLSInterface.addListener((eventObj) => {
console.log(JSON.stringify(eventObj));
});
myLSInterface.set('foo', 'bar');
See live (can't be done on SO due to security issues):
https://jsfiddle.net/0pgyxotn/
From Web_Storage_API
if you load this page in another tab, then make changes to your
choices in the landing page, you'll see the updated storage
information outputted as the StorageEvent is fired
So basically it means that if the storage is changed from another tab then it will reflect in the landing page.
Take an example of this demo. If you open this link in two different tab , you will see the changes in the second tab is reflecting in the first tab, while he change in the first tab is not reflecting in the same page.
There is one addon on mdn. You can also explore this
I am developing a react-redux application where once the user logs in, I was to store some information about the user in local storage. This is so that I can easily retrieve the user information when they perform a action.
If the user close the browser window, I would like to clear all localstorage for the react application. How can I achieve that?
You can just use the JS function :
localStorage.clear();
Firing the event on close of the window
window.onbeforeunload = function() {
localStorage.clear();
}
You could consider using Window.sessionStorage instead of Window.localStorage.
Data stored in sessionStorage gets cleared when the page session ends. A page
session lasts for as long as the browser is open and survives over
page reloads. Source.
You can use localStorage.clear but you have to watch for window close event. Another possible solution is you can use session storage so it will be available until your browser is open. After that session will be removed, so you don't need to do anything.
To clear a localStorage data on browser close, you can use the window.onunload event to check for tab close.
window.onunload = () => {
// Clear the local storage
window.MyStorage.clear()
}
You can make use of the NPM package react-beforeunload
Implementing react-beforeunload on NextJS (Typescript)
On your main file (in NextJS world: _app.tsx) do the following:
...
import { Beforeunload } from 'react-beforeunload';
const removeApplicationData = () => {
if (window) { // NextJS is ServerSideRendering, therefore the window-check.
localStorage.clear();
}
};
...
return (
<Beforeunload onBeforeunload={removeApplicationData}>
<Component {...pageProps} />
</Beforeunload>
);
I have set something in local storage (where tabId is the id of the triggering tab [onUpdated event])
var visited = {};
visited[tabId] = true;
chrome.storage.local.set(visited);
I then wish to change the stored variable to false when the page unloads (which I gather happens on refresh, moving to a new webpage or closing the tab)
window.onunload = resetStorage;
function resetStorage() {
var visited = {};
chrome.tabs.query({ currentWindow: true }, function (result) {
result.forEach(function (tab) {
visited[tab.id] = false;
console.log(visited);
chrome.storage.local.set(visited);
});
});
};
But this doesn't seem to be triggering (I can't get a console.log to come out, not sure if you can on an unload event?) as it does not change the stored values.
What am I doing wrong?
As some background I am keeping track of whether I have already run code on a page so that it doesn't trigger multiple times from iframe loading or redirections (I think I need additional code to handle redirects).