Home > Software design >  Why is a string that is saved to local storage from a form input blank?
Why is a string that is saved to local storage from a form input blank?

Time:11-03

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);
}

CodePudding user response:

You need to check #name value inside the function.

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

CodePudding user response:

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.

CodePudding user response:

  <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

CodePudding user response:

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>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related