Why is a string that is saved to local storage from a form input blank?

I’m trying to make a form that saves the data when the user presses a button.

   <form>
   <label for="name">Name:</label>
   <input type="text" id="name" name="name">
   <label for="age">Age:</label>
   <input type="text" id="age" name="age">
   <button type="button" onclick="SaveData()">Save Data</button>
   <button type="button" onclick="LoadData()">Load Data</button>
   </form>

Here is my attempt. When I try to load the data, it is just blank.

var name = document.getElementById("name").value;
function SaveData() {
    localStorage.setItem("name", name);     
}
function LoadData() {
    var data = localStorage.getItem("name");
    alert(data);
}

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You need to check #name value inside the function.

function SaveData() {
  var name = document.getElementById("name").value;
  localStorage.setItem("name", name);     
}

Method 2

Note that name is set outside saveData() and never updated. Thus, whenever saveData() is called, it’s always storing the original value of name, which (since the form input has no default) is the empty string. Thus it’s more accurate to say that it’s loading the default value, rather than a blank value.

To store the current value of the input, you’ll need to update name before each time saveData() is called or access the value directly in saveData(). Since there are multiple inputs, you’d need to do this for each input. A simple solution is to pass the form to saveData() and have it examine each of the inputs in the form:

function saveData(form) {
    for (elt of form.elements) {
        if (elt.id || elt.name) {
            localStorage.setItem(elt.id || elt.name, elt.value);
        }
    }
}

The “Save” form button would be updated as:

<button type="button" onclick="SaveData(this.form)">Save Data</button>

You can make similar changes to LoadData() and the “Load” button.

Instead of calling the data saving & loading functions from the onclick properties, you could also make use of addEventListener (which has certain advantages, as outlined both in the linked MDN document and “addEventListener vs onclick” here on SO), though passing the form would be handled differently.

Method 3

  <form onsubmit="onSave()">
   <label for="name">Name:</label>
   <input type="text" id="name" name="name">
   <label for="age">Age:</label>
   <input type="text" id="age" name="age">
   <input type="submit" value="Save Data" />
   <button type="button" onclick="LoadData()">Load Data</button>
   </form>
function onSave(event){
    event.preventDefault();
    const { currentTarget } = event;
    const data = new FormData(currentTarget)
    Array.from(data.entries()).forEach(function([key, value]) {
      window.localStorage.setItem(key, value);
    })
}

OR

  <form id="form">
   <label for="name">Name:</label>
   <input type="text" id="name" name="name">
   <label for="age">Age:</label>
   <input type="text" id="age" name="age">
   <button type="button" onclick="SaveData()">Save Data</button>
   <button type="button" onclick="LoadData()">Load Data</button>
   </form>
const form = document.getElementById("form")
function onSave(event){
    const data = new FormData(form)
    Array.from(data.entries()).forEach(function([key, value]) {
      window.localStorage.setItem(key, value);
    })
}

Check this for more information

Method 4

Besides the mistake of acquiring name not from within the SaveData function one does not really want to save all the form data form-control wise each as key-value to the local storage. One should think about saving all of it.

A viable approach was to utilize both FormData and JSON.stringify in order to store all the form’s active data at once under a single form related/specific key.

// local storage mock due to SO blocking
// built-in `localStorage` by privacy settings.
const localStorage = {
  storage: new Map,
  setItem(key, value) {
    this.storage.set(key, value);
  },
  getItem(key) {
    return this.storage.get(key) ?? null;
  }
};

function saveData(evt) {
  evt.preventDefault();

  const elmForm = evt.currentTarget;
  const storageKey = elmForm.dataset.storableForm;

  const activeData = Object.fromEntries(
    Array.from(
      new FormData(elmForm).entries()
    )
  );
  localStorage.setItem(
    storageKey,
    JSON.stringify(activeData)
  );

  // debug logging.
  console.log({
    [storageKey]: localStorage.getItem(storageKey)
  });
}
function loadData(evt) {
  const elmForm = evt.currentTarget.form;
  const storageKey = elmForm.dataset.storableForm;

  const storageData = JSON.parse(
    localStorage.getItem(storageKey)
  );
  Object
    .entries(storageData ?? {})
    .forEach(([key, value]) => {
      elmForm.elements[key].value = value;
    });

  // debug logging.
  console.log({ storageData });
}

document
  .querySelectorAll('[data-storable-form]')
  .forEach(elmNode => {
    elmNode
      .addEventListener('submit', saveData);
    elmNode
     .querySelector('[data-load]')
     .addEventListener('click', loadData);
  });
body { margin: 0; zoom: .95; }
.as-console-wrapper { min-height: 85%!important; }
<form data-storable-form="form-data-A">
  <label for="name">Name:</label>
  <input type="text" id="name" name="name">

  <label for="age">Age:</label>
  <input type="text" id="age" name="age">

  <button type="submit">Save Data</button>

  <button type="reset" onclick="console.clear();">Clear Data</button>

  <button type="button" data-load>Load Data</button>
</form>


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x