javascripthtmlgoogle-chromelocal-storagemicrosoft-edge

Unsaved Checkbox State with localStorage in Chrome and Edge


I'm trying to save and restore the state of a checkbox and other elements using localStorage when a user duplicates or closes the tab. It works well when I have just the checkbox, but as soon as I introduce additional elements, the checkbox state is not saved correctly in Chrome and Edge. Inspired by a similar issue discussed here, I created a version demonstrating the problem:

function save() {
  var checkbox = document.getElementById('checkbox1zaal1');
  var textarea = document.querySelector('textarea');
  localStorage.setItem('checkbox1zaal1', checkbox.checked);
  localStorage.setItem('box', textarea.value);
}

function load() {
  var checked = JSON.parse(localStorage.getItem('checkbox1zaal1'));
  document.getElementById("checkbox1zaal1").checked = checked;
  document.querySelector('textarea').value = JSON.parse(localStorage.getItem('box'));
}

function wis() {
  location.reload();
  localStorage.clear();
}

load();
<input type="button" id="ReserveerButton1" value="save" onclick="save()" />
<input type="button" id="Wisbutton1" value="delete" onclick="wis()" />
<input type="checkbox" id="checkbox1zaal1">
<textarea>Hello, world!</textarea>

DEMO

Steps to reproduce the issue:

  1. Navigate to the demo page.
  2. Just check the checkbox.
  3. Click the save button.
  4. Duplicate the tab.

The checkbox on the duplicate tab is not checked.

What am I missing? Is this a known bug in Chrome and Edge, or is there another approach I can try to ensure that the checkbox state is saved correctly alongside the other elements?


Solution

  • There is one major issue with your code: You are using JSON.parse without actually JSON.stringifying the values, you are trying to parse later on. This leads to an error, when you trying to parse the value for the textarea. This error can easily be seen, when you open the chrome developer tools ...

    So I'd suggest to fix your load by getting rid of the JSON.parse

    function load(){
        var checked = localStorage.getItem('checkbox1zaal1') === "true";
        document.getElementById("checkbox1zaal1").checked = checked;
        document.querySelector('textarea').value = localStorage.getItem('box');
    }
    

    But even with that error fixed, it still doesn't work as expected (at least with Chrome based browsers. It works with Safari). Not sure why it fails,though, because (at least for me) it only fails on the initial load in the new tab. Ie if I do a "Refresh" in the newly created tab it works as expected.

    But I can get it to work if I do

    setTimeout(load, 0)
    

    instead of

    load();
    

    This seems like some sort of timing issue or race condition in the browser engine. Maybe someone with more insights can give an explanation here. With using the setTimeout we are actually not calling the load synchronously within the rendering process anymore, but only after the rendering is completed. This seems to make a difference here ...

    It also seems strange that the checkbox is actually cleared on "Duplicate tab", because if I remove the call to load entirely, "Duplicate tab" restores the values of the inputs like they are in the source tab ... So maybe this is a conflict/timing issue between restoring the input-values by the "Duplicate" operations and updating the inputs from the script. This assumption may also explain, why everything works as expected if one does a "Refresh" on the duplicated tab. And more strangely it also seems to work, if the textarea is not empty when saving or when I remove the textarea and all related code entirely ...

    So this is probably not the canonical answer you are looking for. For me it seems more like a bug in Chrome (and derived browsers like Edge or Brave). Especially because it works as expected in non-Chrome browsers like Safari or Firefox and it also works in Chrome-based browsers when you do a refresh or just paste the url into a new empty tab. Maybe it's even depending on the version and/or OS version because it alledegly works for other users also in Chrome. You may try filing an issue with Chromium (but I suggest you fix the errors with JSON.parse first)