I've got a project doing something similar. It has several core fields but users can add in their own fields, all of which are rendered dynamically. We store the fields in as json in a section_schema table with 4 columns: |id | section_name | schema | disable
The schema contains anything that we would need to render the dynamic form. Some of the specific formatting for our core data gets a little clunky but it works pretty well. I skipped the prep we do on the backend because I didn't want this to get too long. Here are the basics:
basic json in section_schema:
{
"Company Name":{
"cols":"8",
"field_name": "company_name",
"type":"string",
"order":"0",
"required":"1"
},
"Member Type":{
"cols":"4",
"field_name": "member_type",
"type":"dropdown_fromdata",
"order":"1",
"required":"1",
"dropdown":{"table" : "membershipType", "field": "name"}
},
"Website":{
"cols":"4",
"field_name": "company_website",
"type":"string",
"order":"2",
"required":"0"
},
... others
in vue component:
<div class="col-sm-6" v-for="v in dataType">
<div class="white-box">
<h3 class="box-title">{{v.section_name}}</h3>
<form class="form-material form-horizontal m-t-30" :id="v.section_id">
<input type="hidden" :value="v.section_id" id="type" name="type">
<div class="form-group" v-for="i in v.field_data">
<label class="col-md-12" :for="i.id">{{i.name}}</span></label>
<div class="col-md-12">
<select v-if="i.id === 'company_info-member_type'" class="form-control" style="width: 100%;" size="1" :value="i.value" :id="i.id" :name="i.id">
<option value="" selected disabled>Please select</option>
<option v-for="mt in membershipTypes" :value="mt.name">{{mt.name}}</option>
</select>
<select v-else-if="i.id === 'company_info_status'" class="form-control" style="width: 100%;" size="1" :value="i.value" :id="i.id" :name="i.id">
<option value="" selected disabled>Please select</option>
<option v-for="status in statuses" :value="status.name">{{status.name}}</option>
</select>
<datepicker v-else-if="i.id === 'company_info-anniversary'" :format="format" :value="setDate(i.value)" :id="i.id" :name="i.id"></datepicker>
<input v-else-if="i.type == 'phone'" :type="i.type" :id="i.id" :name="i.id" class="form-control" :placeholder="i.name" :value="i.value" data-mask="(999) 999-9999">
<input v-else :type="i.type" :id="i.id" :name="i.id" class="form-control" :placeholder="i.name" :value="i.value">
</div>
</div>
<button @click.prevent="saveMemberChanges(v.section_id)" class="btn btn-info waves-effect waves-light m-r-10">Submit</button>
</form>
</div>
</div>
Edit: more info
Our data:
data () {
return {
dataType: [],
}
},
methods: {
getDataTypes: function(){
var id = this.member.id
this.$http.get('/member/details/json/'+id).then((response) => {
var data = response.data
this.dataType = data
}, (response) => {
...
});
},
}