Hi,
I have created a Vue component for the edit and new function of a Datatable. (Inspired by this: https://adamwathan.me/2016/01/04/composing-reusable-modal-dialogs-with-vuejs/)
What I would like to do now, is to make this reusable for my other Datatables. This means that it would need to have different fields on and slightly different functionality depending on the field type.
Can anyone suggest where to start with this? Has anyone done anything similar?
I am guessing that maybe I could extract the fields HTML and use a slot for this.
I will need the functionality to have a file uploads, selects, dates, text and textarea fields.
<template>
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title"> {{ modalTitle }} </h4>
</div>
<form class="form-horizontal" role="form">
<input type="hidden" name="_method" value="PATCH"><!--needed to get to store-->
<div class="modal-body">
<div class="row">
<div class="form-group">
<label for="report_type_id" class="col-sm-1 control-label">Type</label>
<div class="col-sm-4">
<select v-model="report_type_id" id = "report_type_id" class="form-control">
<option disabled value="">Please select one</option>
<option v-for="report_type in typeOptions" v-bind:value="report_type.id">
{{ report_type.name }}
</option>
</select>
</div>
<label for="area_id" class="col-sm-1 control-label">Area</label>
<div class="col-sm-4">
<select v-model="area_id" id = "area_id" class="form-control">
<option disabled value="">Please select one</option>
<option v-for="area in areaOptions" v-bind:value="area.id">
{{ area.name }}
</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-12">
<div class="form-group">
<label for="name" class="col-sm-1 control-label">Name</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="name" v-model="name" required>
</div>
</div>
</div>
</div>
</div>
<div v-if="report_type_id == 1">
<div class="row">
<div class="form-group">
<label for="sql" class="col-sm-1 control-label">SQL</label>
<div class="col-sm-11">
<textarea class="form-control" rows="5" columns="200" id="sql" v-model="SQL" required></textarea>
</div>
</div>
</div>
</div>
<div v-else>
File Upload
</div>
</div>
</form>
<div class="modal-footer">
<button type="button" @click="closeForm" class="btn btn-default">Cancel</button>
<button type="button" @click="saveData" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
//need one of these for each element
title:"",
name:"",
SQL:"",
area_id:"",
report_type_id:"",
hiddenId:"",
areaOptions:[],
typeOptions:[]
}
},
props: ['table','rowId','modalTitle','mode'],
created: function () {
this.loadSelects();
},
methods: {
loadSelects: function (event) {
let self = this;
axios.get('/reports/selects')
.then(function (response) {
//populate the selects
self.areaOptions = response.data.areas;
self.typeOptions = response.data.reportTypes;
if(self.mode=="edit"){
self.loadData();
}else{
self.clearData();
}
})
.catch(function (error) {
console.log(error);
});
},
clearData: function (event) {
self.name = "";
self.SQL = "";
self.area_id = "";
self.report_type_id = "";
},
loadData: function (event) {
let self = this;
axios.get('/' + self.table + '/' + self.rowId + '/edit')
.then(function (response) {
self.name = response.data.record.name;
self.SQL = response.data.record.sql;
self.area_id = response.data.record.area_id;
self.report_type_id = response.data.record.report_type_id;
})
.catch(function (error) {
console.log(error);
});
},
closeForm: function (event) {
this.$emit('close');
},
saveData: function (event) {
if(this.mode=="edit"){
this.update();
}else{
this.store();
}
},//saveData
update: function (event) {
let self = this;
//update - | PUT|PATCH | widgets/{widget}
axios.patch('/' + self.table + '/' + self.rowId,{
name: self.name,
sql:self.SQL,
area_id:self.area_id,
report_type_id:self.report_type_id
})
.then(function (response) {
self.closeForm();
sweetSuccess('Record updated.');
})
.catch(function (error) {
displayFieldErrors(JSON.parse(error.response.request.responseText));
});
},//update
store: function (event) {
let self = this;
//POST /photos store photos.store
axios.post('/' + self.table,{
name: self.name,
sql:self.SQL,
area_id:self.area_id,
report_type_id:self.report_type_id
})
.then(function (response) {
self.closeForm();
sweetSuccess('Record created.');
})
.catch(function (error) {
displayFieldErrors(JSON.parse(error.response.request.responseText));
});
}//store
}//methods
}//export
</script>
Please note that I am also allowing the users to insert SQL into my database. This may seem slightly insane, but this application will be used by the IT department, to create reports for users. This is a key requirement of this system and it will only be used internally. (I may add some validation, to only allow SELECTS!).
Can anyone think of a better way to do this?:
<div v-if="report_type_id == 1">
The 1 is the id in the table, different report types require different fields.
Thanks,
Mick