4
votes

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).

1
Your code seems correct, what's the issue?Boussadjra Brahim
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.ImranR
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' () {...} }.skirtle
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 },ImranR
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/localStorageskirtle

1 Answers

1
votes

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