6

I have created a form and I'm trying to understand how to use v-model with nested properties in Vue.js

This is the code for my template, as you can see I'm trying to reference the nested properties like so: form.dobDate, but how do I reference the properties (dobDate, dobMonth and dobYear) in mounted and watch? So that whatever I type remains there on page refresh?

<template>
  <div>
    <b-form novalidate>
      <b-form-select name="dobDate" id="dobDate" v-model="form.dobDate" :options="optionsDays"></b-form-select>

      <b-form-select name="dobMonth" id="dobMonth" v-model="form.dobMonth" :options="optionsMonths"></b-form-select>

      <b-form-input
        placeholder="Year of Birth"
        required
        autofocus
        class="form-control"
        name="year"
        id="year"
        min="0"
        max="2003"
        type="number"
        v-model="form.dobYear"
      ></b-form-input>

      <input type="text" v-model="name" />

      <b-button type="submit" variant="primary">Submit</b-button>
    </b-form>
    <b-card class="mt-3" header="Form Data Result">
      <pre class="m-0">{{ form }}</pre>
    </b-card>
  </div>
</template>

Here is script code:

<script>
export default {
  data() {
    return {
      name: "",
      form: {
        dobDate: {
          selected: ""
        },
        dobMonth: {
          selected: ""
        },
        dobYear: "",
        name: ""
      },
      optionsMonths: [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"
      ],
      show: true
    };
  },

  mounted() {
    if (localStorage.name) {
      this.name = localStorage.name;
    }
  },
  watch: {
    name(newName) {
      localStorage.name = newName;
    },
    deep: true
  },

  computed: {
    optionsDays() {
      return Array.from(Array(31).keys());
    }
  },

  methods: {
    onSubmit(evt) {
      evt.preventDefault();
      alert(JSON.stringify(this.form));
    },
    getDates() {
      return Array.from(Array(31).keys());
    }
  }
};
</script>

As you can see I have a form object, with nested properties inside it which I want to bind to, and I'm also using mounted() and watch to store the data in local storage for when the page refreshes or when submitting the form (no validation at the moment).

5
  • Your code seems correct, what's the issue? Commented Aug 28, 2019 at 11:38
  • I want to find out how to reference the properties in the mounted method and when watching, so that the data remains on the page during page refresh or when submitting. Commented Aug 28, 2019 at 11:45
  • Not really following. Isn't it just this.form.dobDate in mounted? For the watch you'd need quotes around the property key, watch: { 'form.dobDate' () {...} }. Commented Aug 28, 2019 at 11:48
  • I tried this, but this doesn't work, what am I doing wrong?: mounted() { if (localStorage.name) { this.name = localStorage.name; this.form.dobDate = localStorage.form.dobDate; } }, watch: { name(newName) { localStorage.name = newName; }, "form.dobDate"(newDate) { localStorage.form.name = newDate; }, deep: true }, Commented Aug 28, 2019 at 11:55
  • localStorage allows you to store strings, not objects. You will need to suitably encode them. Some background reading: developer.mozilla.org/en-US/docs/Web/API/Window/localStorage Commented Aug 28, 2019 at 12:16

1 Answer 1

2

You could watch the form deeply (accessing its nested field ) and loop through it values using :

  Object.keys(after).forEach(key=>{
          localStorage[key]=after[key]
       })
 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

sorry I didn't understand how to use this for the solution, something like this? watch: { form: { handler(newval) { localStorage = newVal; }, deep: true } },
Yes, something like localStorage.name = newval.name;
Thanks, I ended up using the following: handler: function(after, before) { Object.keys(after).forEach(key => { localStorage[key] = after[key]; }); }, deep: true
you're welcome i edited my answer by explaining it more better

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.