- Accompanying css - Views to serve the Chat Client - first test version of the TRACIE_SELECTION_SPECIALIST - ESS Implemented.
110 lines
3.9 KiB
JavaScript
110 lines
3.9 KiB
JavaScript
export const DynamicForm = {
|
|
name: 'DynamicForm',
|
|
props: {
|
|
formData: {
|
|
type: Object,
|
|
required: true,
|
|
validator: (formData) => {
|
|
return formData.title && formData.fields && Array.isArray(formData.fields);
|
|
}
|
|
},
|
|
formValues: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
isSubmitting: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
emits: ['submit', 'cancel'],
|
|
methods: {
|
|
handleSubmit() {
|
|
// Basic validation
|
|
const requiredFields = this.formData.fields.filter(field => field.required);
|
|
const missingFields = requiredFields.filter(field => {
|
|
const value = this.formValues[field.name];
|
|
return !value || (typeof value === 'string' && !value.trim());
|
|
});
|
|
|
|
if (missingFields.length > 0) {
|
|
const fieldNames = missingFields.map(f => f.label).join(', ');
|
|
alert(`De volgende velden zijn verplicht: ${fieldNames}`);
|
|
return;
|
|
}
|
|
|
|
this.$emit('submit');
|
|
},
|
|
|
|
handleCancel() {
|
|
this.$emit('cancel');
|
|
},
|
|
|
|
updateFieldValue(fieldName, value) {
|
|
// Emit an update for reactive binding
|
|
this.$emit('update-field', fieldName, value);
|
|
}
|
|
},
|
|
template: `
|
|
<div class="dynamic-form">
|
|
<div class="form-title">{{ formData.title }}</div>
|
|
|
|
<div v-if="formData.description" class="form-description">
|
|
{{ formData.description }}
|
|
</div>
|
|
|
|
<form @submit.prevent="handleSubmit" novalidate>
|
|
<form-field
|
|
v-for="field in formData.fields"
|
|
:key="field.name"
|
|
:field="field"
|
|
:model-value="formValues[field.name]"
|
|
@update:model-value="formValues[field.name] = $event"
|
|
></form-field>
|
|
|
|
<div class="form-actions">
|
|
<button
|
|
type="submit"
|
|
class="btn btn-primary"
|
|
:disabled="isSubmitting"
|
|
:class="{ 'loading': isSubmitting }"
|
|
>
|
|
<span v-if="isSubmitting" class="spinner"></span>
|
|
{{ isSubmitting ? 'Verzenden...' : (formData.submitText || 'Versturen') }}
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
class="btn btn-secondary"
|
|
@click="handleCancel"
|
|
:disabled="isSubmitting"
|
|
>
|
|
{{ formData.cancelText || 'Annuleren' }}
|
|
</button>
|
|
|
|
<!-- Optional reset button -->
|
|
<button
|
|
v-if="formData.showReset"
|
|
type="reset"
|
|
class="btn btn-outline"
|
|
@click="$emit('reset')"
|
|
:disabled="isSubmitting"
|
|
>
|
|
Reset
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Progress indicator for multi-step forms -->
|
|
<div v-if="formData.steps && formData.currentStep" class="form-progress">
|
|
<div class="progress-bar">
|
|
<div
|
|
class="progress-fill"
|
|
:style="{ width: (formData.currentStep / formData.steps * 100) + '%' }"
|
|
></div>
|
|
</div>
|
|
<small>Stap {{ formData.currentStep }} van {{ formData.steps }}</small>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
`
|
|
}; |