1- <script setup>
1+ <script setup lang="ts">
2+ import type { FieldValidation , FormGeneratorProps , FormOptions } from ' @/resources/types/generic'
3+ import type { Field } from ' @/resources/types/field/fields'
4+ import type { ComponentPublicInstance , ComputedRef , Ref } from ' vue'
25import { computed , ref } from ' vue'
36import { resetObjectProperties , toUniqueArray } from ' @/helpers'
47import FormGroup from ' ./FormGroup.vue'
58
6- const emits = defineEmits ([ ' submit' ])
9+ const emits = defineEmits ([ ' submit' , ' field-validated ' ])
710
8- const props = defineProps ({
9- id: {
10- type: String ,
11- required: false ,
12- default: ' '
13- },
14- idPrefix: {
15- type: String ,
16- required: false ,
17- default: ' '
18- },
19- options: {
20- type: Object ,
21- default : () => ({})
22- },
23- schema: {
24- type: Object ,
25- required: true
26- },
27- model: {
28- type: Object ,
29- required: true
30- },
31- enctype: {
32- type: String ,
33- default: ' application/x-www-form-urlencoded'
34- }
11+ const props = withDefaults (defineProps <FormGeneratorProps >(), {
12+ enctype: ' application/x-www-form-urlencoded' ,
13+ id: ' ' ,
14+ idPrefix: ' '
3515})
3616
17+ type FormGroupInstance = ComponentPublicInstance <InstanceType <typeof FormGroup >>
3718/** Data / Refs */
38- const fieldElements = ref ([])
39- const formErrors = ref ({})
40- const formOptions = computed (() => ({ ... props .options , idPrefix: props .idPrefix }))
19+ const fieldElements: Ref < FormGroupInstance []> = ref ([])
20+ const formErrors: Ref < Record < string , any >> = ref ({})
21+ const formOptions: ComputedRef < FormOptions > = computed (() => ({ ... props .options , idPrefix: props .idPrefix }))
4122
4223/**
4324 * Update form model key with its new value.
4425 * @param {String} model model key to update.
4526 * @param {any} value value to set.
4627 */
47- const updateGeneratorModel = ({ model, value }) => {
28+ const updateGeneratorModel = ({ model , value }: { model : string , value : any } ) => {
4829 // eslint-disable-next-line vue/no-mutating-props
4930 props .model [model ] = value
5031}
@@ -54,7 +35,8 @@ const updateGeneratorModel = ({ model, value }) => {
5435 * @param fieldErrors errors discovered during validation of the field.
5536 * @param field field schema object that has been validated.
5637 */
57- const onFieldValidated = ({ fieldErrors, field }) => {
38+ const onFieldValidated = ({ fieldErrors , field }: FieldValidation ) => {
39+ emits (' field-validated' , { fieldErrors , field })
5840 if (! fieldErrors .length ) {
5941 if (! (field .model in formErrors .value )) return
6042 else {
@@ -67,22 +49,23 @@ const onFieldValidated = ({ fieldErrors, field }) => {
6749
6850/** Compute if the form has errors */
6951const hasErrors = computed (() => {
70- return Boolean (Object .values (formErrors .value ).map (e => Boolean (e .length )).filter (e => e === true ).length )
52+ return Boolean (Object .values (formErrors .value ).map (e => Boolean (e .length )).filter (e => e ).length )
7153})
7254
7355/**
7456 * Handle the submit event from the form element.
7557 */
7658const onSubmit = () => {
77- if (hasErrors .value === false ) emits (' submit' )
59+ if (! hasErrors .value ) emits (' submit' )
7860}
7961
8062const onReset = () => {
81- // eslint-disable-next-line vue/no-mutating-props
82- props .model = resetObjectProperties (props .model )
63+ // Hideous hack to update the model, without TypeScript crying about mutation of props. And yes, I know it isn't
64+ // recommended to update the props.
65+ (props as any ).model = resetObjectProperties (props .model )
8366}
8467
85- defineExpose ({ hasErrors })
68+ defineExpose ({ hasErrors , formErrors })
8669 </script >
8770
8871<template >
@@ -95,8 +78,8 @@ defineExpose({ hasErrors })
9578 >
9679 <fieldset v-if =" props.schema.fields" >
9780 <template v-for =" field in props .schema .fields " :key =" field " >
98- <form-group
99- :ref =" el => fieldElements.push(el) "
81+ <FormGroup
82+ :ref =" el => (el && '$el' in el) ? fieldElements.push((el as FormGroupInstance)) : null "
10083 :form-options =" formOptions"
10184 :field =" field"
10285 :model =" props.model"
@@ -110,8 +93,8 @@ defineExpose({ hasErrors })
11093 {{ group.legend }}
11194 </legend >
11295 <template v-for =" field in group .fields " :key =" field " >
113- <form-group
114- :ref =" el => fieldElements.push(el) "
96+ <FormGroup
97+ :ref =" el => (el && '$el' in el) ? fieldElements.push((el as FormGroupInstance)) : null "
11598 :form-options =" formOptions"
11699 :field =" field"
117100 :model =" props.model"
0 commit comments