How to get the values from the DOM controls when the models are created dynamically using vuejs

Viewed 1024

I am creating a dynamic form generator component in which the DOM controls to be displayed are getting populated from an API service. The model key i.e. the :v-model is also getting added dynamically. I am not able to access the data which the user inputs in the DOM control.

The component from where all the data is passed to the form-generator

<template>
   <form-generator :schema="schema" :model="model" :options="formOptions"></form-generator>
</template>
<script>
   export default {
      components: {
        FormGenerator
      },
      data() {
        return {
          model: {},
          schema: {
            fields: [{"id":"dcno1","label":"DC No.","model":"dcno","name":"dcno","ref":"dcno","className":"","type":"input","inputType":"text","required":true,"order":2}]
          }
      }
    }
</script>

In the above code, model and schema.fields are getting populated from an async axios API call.

If we pass value in the model for the model named "dcno", the value is getting filled in the input control


Dynamic Form Generator Component

<template>
   <v-form v-if='schema!==null' v-model="model.valid" ref="form" lazy-validation>
     <v-flex xs6 v-for='(formItem,index) in schema.fields' v-bind:key='index'>
         <v-text-field :v-model='formItem.model' ref="formItem.model" 
            :label='formItem.label' :rules='formItem.rules' 
            :value='model[formItem.model]'
            :type='formItem.inputType' :value='model[formItem.model]' 
            :id='formItem.id'>
         </v-text-field>
      </v-flex>
      <v-btn class='float-right' color="primary" @click="submitForm">Submit</v-btn>
   </v-form>
</template>
<script>
   export default {
     name: 'form-generator',
     components: {
     },
     props: {
     schema: Object,
     model: Object
     },
     methods:{
         submitForm: function(e) {
            //how to access the form model values here
         }
     }
   }
</script>

When passed a static value to model dcno, :value='model[formItem.model]', the value is getting displayed. Consider the fields key has a set of controls. Please help me in getting the values of the form in the submit function.

1 Answers

As you can see in the docs you cannot change the value of a component property, you need to create a support object inside the inner component and emit its value to the main component. Take a look at the example, i create innerModel based on the schema structure then i emit every changes to the innerModel by watching it.

Vue.config.devtools = false;
Vue.config.productionTip = false;
const formGenerator = Vue.component('form-generator', {
  props: ['schema', 'value'],
  data() {
    return {
      innerModel: [],
    }
  },
  watch: {
    schema: {
      deep: true,
      immediate: true,
      handler() {
        this.innerModel = this.schema.fields.map((field) => ({
          // pass here any other property you need
          name: field.name,
          value: field.model,
        }));
      },
    },
    innerModel: {
      deep: true,
      immediate: true,
      handler(value) {
        this.$emit('input', value);
      },
    }
  },
  methods: {
    submitForm: function(e) {
      e.preventDefault();
      // convert innerModel into an object if needed
      console.log(this.innerModel);
    }
  },
  template: `
   <form @submit="submitForm">
     <input
       :key="model.name"
        v-model="model.value"
        v-for="model in innerModel">
     <button type="submit">SUBMIT</button>
    </form>
  `
})

new Vue({
  el: '#app',
  components: {
    formGenerator
  },
  data: {
    model: {},
    schema: {
      fields: [{
        id: "dcno1",
        label: "DC No.",
        model: "dcno",
        name: "dcno",
        ref: "dcno",
        className: "",
        type: "input",
        inputType: "text",
        required: true,
        order: 2
      }]
    }
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <form-generator :schema="schema" v-model="model"></form-generator>
  <h2>Changing model</h2>
  {{ model }}
</div>

Related