aboutsummaryrefslogtreecommitdiff
path: root/front-end/src/components/DynamicForm.vue
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-07-12 01:28:23 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-07-12 01:28:23 -0400
commitf64955c69d91e578e580b409ba31ac4b3477da96 (patch)
tree16f01392ddf1abfea13d7d1ede3bfb0459fe8f0d /front-end/src/components/DynamicForm.vue
Initial commit
Diffstat (limited to 'front-end/src/components/DynamicForm.vue')
-rw-r--r--front-end/src/components/DynamicForm.vue92
1 files changed, 92 insertions, 0 deletions
diff --git a/front-end/src/components/DynamicForm.vue b/front-end/src/components/DynamicForm.vue
new file mode 100644
index 0000000..137ca3b
--- /dev/null
+++ b/front-end/src/components/DynamicForm.vue
@@ -0,0 +1,92 @@
+<template>
+
+ <form :id="form.id" class="dynamic-form form" :path="path" @submit.prevent="onSubmit">
+
+ <fieldset class="dynamic-form input-group" :disabled="disabled">
+
+ <!-- Create a new div element for each field in the form -->
+ <div v-show="!field.hidden"
+ v-for="field in fields"
+ :key="field"
+ :class="{ 'dirty': field.validator.$dirty, 'data-invalid': field.validator.$invalid }"
+ class="dynamic-form input-container"
+ >
+ <!-- label above the fields -->
+ <label :for="field.id" class="dynamic-form input-label" >
+ {{ field.label }}
+ </label>
+
+ <!-- Determine select, input, or textarea -->
+ <select v-if="isSelect(field)"
+ v-model="field.validator.$model"
+ :id="field.id"
+ :disabled="field.disabled"
+ class="dynamic-form dynamic-input input-select"
+ @change="onInput(field)"
+ >
+
+ <option v-for="option in field.options" :key="option.value" :value="option.value">
+ {{ option.label }}
+ </option>
+
+ </select>
+
+ <textarea v-else-if="isTextArea(field)"
+ v-model="field.validator.$model"
+ :id="field.id"
+ :disabled="field.disabled"
+ class="dynamic-form dynamic-input input-textarea"
+ @input="onInput(field)"
+ />
+
+ <input v-else
+ v-model="field.validator.$model"
+ :id="field.id"
+ :type="field.type"
+ :name="field.name"
+ :disabled="field.disabled"
+ class="dynamic-form dynamic-input input"
+ :placeholder="placeholder(field)"
+ @input="onInput(field)"
+ >
+
+ <div class="dynamic-form field-description">
+ <p>{{ field.description }}</p>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+</template>
+
+<script setup lang="ts">
+import { defaultTo, cloneDeep, forEach } from 'lodash'
+import { toRefs, computed } from 'vue'
+
+const props = defineProps<{
+ form: any
+ disabled?: boolean
+ validator: any
+}>()
+
+const emit = defineEmits(['input', 'submit'])
+
+const { form, disabled, validator } = toRefs(props)
+
+const schema = computed(() => cloneDeep(form.value))
+const path = computed(() => defaultTo(form.value.path, '#'))
+
+const fields = computed(() =>{
+ const ff = defaultTo(schema.value.fields, [])
+ //Set validators for the field, storeing the fields in the schema item
+ forEach(ff, field => field.validator = validator.value[field.name])
+ return ff;
+})
+
+const isSelect = (field : any) => field.type === 'select'
+const isTextArea = (field : any) => field.type === 'textarea'
+const placeholder = (field : any) => defaultTo(field.placeholder, field.label)
+
+const onSubmit = () => emit('submit')
+const onInput = (field : string) => emit('input', field)
+
+</script> \ No newline at end of file