0

I have two pages, 1. x-dashboard page 2. y-dashboard page. x-dashboard is having a table component y-dashoard is also having a table component with different data.

Now, I created a generic filter component , when user clicks on filter icon inside x or y page then I am showing filter options in a popup based on table columns dynamically.

After user enteres some filters and click on apply, I will store that filter value in local storage(the logic is inside filter component) and access that value inside respective page( either x or y page ) based on subscriber.

when you navigate from xpage to ypage using links, I am clearing the local storage key on ngdestroy. So that the next page will not get the same filter params from local storage.

But when I typed the url(navigating through routing), then ngdestroy is not calling and the localstorage(filtered params) setup in x page is showing in y page.

If I clear on page load, then when user refresh he will lose the filtered params. How to solve this issue?enter image description here

Tony
  • 141
  • 4
  • 21

2 Answers2

1

You can set a key for each component that acts like an identifier for the data stored in localStorage. And at each component's ngOnInit, check if the identifier is same with the component's or not.

I created a stackblitz here: https://stackblitz.com/edit/angular-oryk5z

First, I created a model for items to be stored in localStorage:

export class LocalStorageItem{
  last_component: string;
  id: number;
  row: number;
  whatever: string;

  static fromJSON = (jsonValue: string): LocalStorageItem => {

    const newItem = new LocalStorageItem();
    if(jsonValue !== null){
      const parsedJSON = JSON.parse(jsonValue);
      newItem.last_component = parsedJSON['last_component'];
      newItem.id = parsedJSON['id'];
      newItem.row = parsedJSON['row'];
      newItem.whatever = parsedJSON['whatever'];
    }
    return newItem;
  }

}

Then I created a service which is responsible for storage operations. In the initLocalStorage() method, this service takes the component's identifier as a parameter and checks if the stored item's identifier is the same. If not, it creates a new item with the identifier.

export class LocalStorageService {

  readonly filterStorageKey = 'component_storage_key'

  constructor() { }

  initLocalStorage = (storageKey: string) => {

    var storedItem = LocalStorageItem.fromJSON(localStorage.getItem(this.filterStorageKey));



    if (storedItem === null || (storedItem.last_component !== storageKey)) { // if no value is stored / store is empty
      const newStoreItem = new LocalStorageItem();
      newStoreItem.last_component = storageKey;
      this.setLocalStorage(newStoreItem);

    }
    storedItem = LocalStorageItem.fromJSON(localStorage.getItem(this.filterStorageKey)); // this line is for debug purposes
    return storedItem;

  }

  getLocalStorage = () => {
    return LocalStorageItem.fromJSON(localStorage.getItem(this.filterStorageKey));
  }

  setLocalStorage = (item: LocalStorageItem) =>{
    localStorage.setItem(this.filterStorageKey, JSON.stringify(item));
  }

}

And then in each component, call initLocalStorage() method of service at ngOnInit with storage identifier of that component:

export class YDashboardComponent implements OnInit, ILocalStorageManager { // This interface is to be sure that the component defines storageKey property

  readonly storageKey = 'y-dashboard';
  storedItemFromService;
  constructor(private localStorageService: LocalStorageService) { }

  ngOnInit() {
    this.storedItemFromService = this.localStorageService.initLocalStorage(this.storageKey);
  }

}

I hope that will give a clue about what you want to build.

Harun Yilmaz
  • 8,281
  • 3
  • 24
  • 35
  • Thank you for the post. I will try in my project and let you know. Bit busy with other work. – Tony Jun 16 '19 at 08:52
  • If I navigate from X to Y and Y to X, there should not be any stored variable because its brand new page. So , I should clear the filters, In your solution, after setting X key when I navigate to Y dashboard and comes back still its showing x key which is wrong I feel. I want the data to be persist upon page refresh (provided same route refresh F5). 2. Once I go to Y page from X page and comes back to x page again , then local storage should not be there . Because user navigated to another page. – Tony Jun 17 '19 at 18:47
  • 1- When you go route to a component and if the identifier is different, it creates an empty item in storage. And if you F5 refresh, the storage remains same. 2- it clears the storage if the identifier is different. Above code should work for both scenarios. You can play with the code in stackblitz link I provided and check if it works for your needs. If something is not clear, please feel free to ask. – Harun Yilmaz Jun 17 '19 at 18:54
  • Sorry for dragging this, but I am really confused. I opened your stack blitz, click on X dash board button => value stored in local storage key => now click on Y dash board => Y storage key set in local storage => now when I come back to x dashboard (through url .../x-dashboard) then X storage key should be empty right? Instead of that its showing the local storage value. which is wrong – Tony Jun 17 '19 at 19:36
  • 1
    Let's continue to discuss about the question in [this chat room](https://chat.stackoverflow.com/rooms/195085/how-to-remove-local-storage-if-the-component-is-other-than-the-current-component) :) – Harun Yilmaz Jun 17 '19 at 20:16
  • Please modify the code as you suggested over chat, which will be helpful for others, thanks – Tony Jun 18 '19 at 06:38
  • One bug:if user navigates to any other than y-dashboard component and comes back to X dashboard , then also filters are persisting in X-dashboard which is not correct! – Tony Jun 18 '19 at 19:07
  • Actually it is not a bug. It is an intended behaviour. If you want to clear localStorage on every other component init, you can write something like `clearLocalStorage()` and call it on `ngOnInit` of any component. – Harun Yilmaz Jun 19 '19 at 06:04
0

You could add another propery to the object you save in the localStorage (the filter object), such as page: 'pageY', or page: 'pageX', then in your ngOnLoad() you check if the current page matches that property, you use it, otherwise you remove it.

Bruno Farias
  • 785
  • 8
  • 22
  • I kept as the end option :) . I want to maintain a single key, so that I no need to tell to the filter component about the parent page. All working fine if I am navigating using menu router links (executing ngDestroy() - logic to remove the LStorage). But, when I change the router path in URL, then ngDestroy() is not calling. any wrong approach I am following ? – Tony Jun 14 '19 at 14:58
  • When you change the router path in the URL, Angular makes the decision whether it should recreate the page or not, based on the route. If you are navigating to the same route (even though with different parameters), it will remain the same and not call ngOnDestroy(). One solution would be to subscribe to the ActivatedRoute.queryParams Observable so you get notified every time the URL changes in that page. Please see te solution of this question: https://stackoverflow.com/questions/46969864/on-query-parameters-change-route-is-not-updating?noredirect=1&lq=1 – Bruno Farias Jun 14 '19 at 15:10
  • I am not navigating to the same route, I am navigating from abc/x-route-name TO abc/y-route-name – Tony Jun 14 '19 at 15:14
  • I am navigating from http://server/abc/x-route-name TO abc/y-route-name ( 'abc' is common ) – Tony Jun 14 '19 at 17:01
  • as you suggested I did the same but now the issue is, when I navigate from y dashboard to x dashboard the previously stored x dashboard value still exist and filters are applying by default which is wrong. I want to clear the data up on component change. – Abhi just now Edit Delete – Tony Jun 15 '19 at 07:26
  • I think I misunderstood your point, I thought you wanted to save the filter so the next time the users entered the page the filter would be automatically applied. If you only need the filter for the current page, why are you saving it to the localStorage? Usually we save things to localStorage to be retrieved later on. If you don't need it, just save it in a local variable and it will be destroyed once the component is gone. – Bruno Farias Jun 17 '19 at 14:46
  • If you are using Subscribers, you have to put your logic inside the body of the callback, like validating if the localStorage is valid for your page and retrieving the data from localStorage. Basically the logic that used to be on ngOnInit should go to the subscription body. – Bruno Farias Jun 17 '19 at 14:49
  • 1. If I take local variable, then upon refresh the variable value will be gone. I want the data to be persist upon page refresh (provided same route refresh F5). 2. Once I go to Y page from X page and comes back to x page again , then local storage should not be there . Because user navigated to another page. – Tony Jun 17 '19 at 18:25