1

I have this code in my Vue.js component:

mounted() {
    if (localStorage.dobDate) {
      this.form.dobDate = localStorage.dobDate;
    }

    if (localStorage.dobMonth) {
      this.form.dobMonth = localStorage.dobMonth;
    }

    if (localStorage.dobYear) {
      this.form.dobYear = localStorage.dobYear;
    }
  },

  watch: {
    "form.dobDate": {
      handler: function(after, before) {
        localStorage.dobDate = after;
      },
      deep: true
    },
    "form.dobMonth": {
      handler: function(after, before) {
        localStorage.dobMonth = after;
      },
      deep: true
    },
    "form.dobYear": {
      handler: function(after, before) {
        localStorage.dobYear = after;
      },
      deep: true
    }

Ask you can see it can get very repetitive, if for example I had a large form, and I don't want to do this for every field. Is there a way I can approach this to make it more DRY? Is there a way I can make it more dynamic for any field in a form for example?

1
  • something like: ['dobDate', 'dobMonth', 'dobYear'].forEach(e => {if (localStorage[e]) console.log(localStorage[e])});..... Commented Aug 29, 2019 at 12:21

3 Answers 3

3

In the mounted hook create an array of localStorage fields ["dobDate","dobMonth","dobYear"] and loop through it using forEach method, for each field localStorage[fieldName] check if it's defined using conditional operator, if it's defined assign it to the correspondant field name in the form data property else pass to the next element:

mounted(){
["dobDate","dobMonth","dobYear"].forEach(field=>{

localStorage[field]?this.form[field]=localStorage[field]:{};

})

}

In the watch property watch the form object deeply (watch its nested fields) then loop through its keys by doing the reciprocal operation made in mounted hook :

 watch: {
    form: {
      handler: function(after, before) {
        Object.keys(after).forEach(key=>{
          localStorage[key]=after[key]
       })
      },
      deep: true
    }
   }
Sign up to request clarification or add additional context in comments.

4 Comments

Great! That worked perfectly, would you mind briefly explaining the code a little just so I have a better understanding of the approach?
You're welcome, i tried to add some explanation i hope that could help you
Thanks that helped a lot :)
you're welcome, i want just know if my answer on this question helped you or there's some thing to explain?
2

Here is another approach with multiple (no deep) watchers.

data: {
  form: {},
  dateFields: ['dobDate', 'dobMonth', 'dobYear']
},

mounted() {
  for (const dateField of this.dateFields) {
    if (localStorage[dateField])
      this.$set(this.form, dateField, localStorage[dateField])
  }
},

created() {
  for (const dateField of this.dateFields) {
    this.$watch('form.' + dateField, function(after, before) {
      localStorage[dateField] = after;
    });
  }
}

I ignore if it's more or less efficient than only one deep watcher. It may depends on the way your data change.

Comments

1

I'm sure you must have reasons for using localStorage for saving form data in localStorage, so with this code, you can pass the whole form object to localStorage and can retrieve that. in this case, any change in form would make this watch run

mounted() {
    if (localStorage.form) {
      this.form = localStorage.form
    }
  },

 watch: {
    "form": {
      handler: function(after, before) {
        localStorage.form = after;
      },
      deep: true
    }
   }

1 Comment

Just tried this but when refreshing the localstorage doesn't seem to work anymore. I also get a lot of errors, such as Error in v-on handler: "TypeError: Cannot use 'in' operator to search for 'dobYear' in [object Object]"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.