srcdev-nuxt-forms 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/assets/styles/forms/index.css +1 -0
  3. package/assets/styles/forms/themes/_primary.css +2 -0
  4. package/assets/styles/forms/themes/_secondary.css +2 -0
  5. package/assets/styles/forms/utils/_a11y.css +5 -0
  6. package/assets/styles/forms/utils/index.css +1 -0
  7. package/assets/styles/forms/variables/_theme.css +11 -17
  8. package/assets/styles/variables/colors/_gray.css +1 -0
  9. package/components/forms/c12/prop-validators/index.ts +8 -20
  10. package/components/forms/c12/utils.ts +14 -0
  11. package/components/forms/c12/validation-patterns/en.json +12 -0
  12. package/components/forms/form-errors/InputError.vue +132 -0
  13. package/components/forms/input-button/InputButtonCore.vue +11 -8
  14. package/components/forms/input-button/variants/InputButtonConfirm.vue +1 -1
  15. package/components/forms/input-button/variants/InputButtonSubmit.vue +1 -1
  16. package/components/forms/input-checkbox/InputCheckboxCore.vue +407 -0
  17. package/components/forms/input-checkbox/InputCheckboxWithLabel.vue +125 -0
  18. package/components/forms/input-checkbox/variants/MultipleCheckboxes.vue +194 -0
  19. package/components/forms/input-checkbox/variants/SingleCheckbox.vue +157 -0
  20. package/components/forms/input-radio/InputRadioCore.vue +226 -0
  21. package/components/forms/input-radio/InputRadioWithLabel.vue +118 -0
  22. package/components/forms/input-radio/variants/MultipleRadio.vue +183 -0
  23. package/components/forms/input-radio/variants/SingleRadio.vue +131 -0
  24. package/components/forms/input-range/InputRangeCore.vue +171 -0
  25. package/components/forms/input-range/variants/InputRangeDefault.vue +131 -0
  26. package/components/forms/input-text/InputTextCore.vue +61 -31
  27. package/components/forms/input-text/variants/material/InputPasswordMaterial.vue +27 -1
  28. package/components/forms/input-text/variants/material/InputTextMaterial.vue +1 -8
  29. package/components/forms/input-text/variants/material/InputTextMaterialCore.vue +83 -28
  30. package/components/forms/input-textarea/InputTextareaCore.vue +170 -0
  31. package/components/forms/input-textarea/variants/material/InputTextareaMaterial.vue +75 -0
  32. package/components/forms/input-textarea/variants/material/InputTextareaMaterialCore.vue +290 -0
  33. package/components/ui/content-grid/ContentGrid.vue +85 -0
  34. package/composables/useErrorMessages.ts +17 -5
  35. package/composables/useFormControl.ts +147 -37
  36. package/layouts/default.vue +7 -13
  37. package/nuxt.config.ts +22 -0
  38. package/package.json +9 -8
  39. package/pages/forms/examples/buttons/index.vue +14 -13
  40. package/pages/forms/examples/material/text-fields.vue +320 -84
  41. package/pages/limit-text.vue +43 -0
  42. package/server/api/places/list.get.ts +23 -0
  43. package/server/api/textFields.post.ts +37 -0
  44. package/server/api/utils/index.get.ts +20 -0
  45. package/server/data/places/cities.json +37 -0
  46. package/server/data/places/countries.json +55 -0
  47. package/server/data/utils/title.json +49 -0
  48. package/types/types.forms.ts +33 -3
  49. package/types/types.places.ts +8 -0
  50. package/pages/forms/examples/material/text-fields-compact.vue +0 -136
@@ -0,0 +1,290 @@
1
+ <template>
2
+ <div class="input-textarea-material" :class="[`theme-${theme}`, { error: fieldHasError }, { compact: compact }]">
3
+ <label class="input-textarea-label" :for="id" :class="[{ active: isFocused }, { error: fieldHasError }, { dirty: fieldIsDirty }, { compact: compact }]">
4
+ <span>{{ c12.label }}</span>
5
+ </label>
6
+ <div class="input-textarea-container" :class="[{ active: isFocused }, { error: fieldHasError }, { dirty: fieldIsDirty }, { compact: compact }]">
7
+ <slot name="input"></slot>
8
+ </div>
9
+ <InputError :errorMessaging :fieldHasError :id :isDetached="false" />
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import type { InpuTextC12, IFormData } from '@/types/types.forms';
15
+
16
+ import propValidators from '../../../c12/prop-validators';
17
+
18
+ const props = defineProps({
19
+ size: {
20
+ type: String as PropType<string>,
21
+ default: 'normal',
22
+ validator(value: string) {
23
+ return propValidators.size.includes(value);
24
+ },
25
+ },
26
+ weight: {
27
+ type: String as PropType<string>,
28
+ default: 'wght-400',
29
+ validator(value: string) {
30
+ return propValidators.weight.includes(value);
31
+ },
32
+ },
33
+ theme: {
34
+ type: String as PropType<string>,
35
+ default: 'primary',
36
+ validator(value: string) {
37
+ return propValidators.theme.includes(value);
38
+ },
39
+ },
40
+ id: {
41
+ type: String,
42
+ required: true,
43
+ },
44
+ name: {
45
+ type: String,
46
+ default: null,
47
+ },
48
+ required: {
49
+ type: Boolean,
50
+ value: false,
51
+ },
52
+ c12: {
53
+ type: Object as PropType<InpuTextC12>,
54
+ required: true,
55
+ },
56
+ styleClassPassthrough: {
57
+ type: String,
58
+ default: '',
59
+ },
60
+ compact: {
61
+ type: Boolean,
62
+ value: false,
63
+ },
64
+ });
65
+
66
+ const errorMessaging = computed(() => {
67
+ if (
68
+ typeof modelValue.value!.formFieldsC12[props.name] !== 'undefined' &&
69
+ modelValue.value!.formFieldsC12[props.name].useCustomError &&
70
+ modelValue.value.data[props.name] === modelValue.value.formFieldsC12[props.name].previousValue
71
+ ) {
72
+ return modelValue.value.formFieldsC12[props.name]?.customErrors || [];
73
+ } else {
74
+ return props.c12.errorMessage;
75
+ }
76
+ });
77
+
78
+ const modelValue = defineModel() as Ref<IFormData>;
79
+
80
+ const isFocused = computed(() => {
81
+ return modelValue.value.focusedField == props.name;
82
+ });
83
+
84
+ const fieldIsDirty = computed(() => {
85
+ if (typeof modelValue.value!.formFieldsC12[props.name] !== 'undefined') {
86
+ return modelValue.value!.formFieldsC12[props.name].isDirty;
87
+ } else {
88
+ return false;
89
+ }
90
+ });
91
+
92
+ const fieldHasError = computed(() => {
93
+ if (typeof modelValue.value!.formFieldsC12[props.name] !== 'undefined') {
94
+ return modelValue.value!.submitAttempted && !modelValue.value!.formFieldsC12[props.name].isValid;
95
+ }
96
+ return false;
97
+ });
98
+ </script>
99
+
100
+ <style lang="css">
101
+ .input-textarea-material {
102
+ --_form-theme: var(--theme-form-primary);
103
+ --_focus-colour: var(--theme-form-primary-focus);
104
+ --_gutter: 12px;
105
+ --_border-width: var(--input-border-width-thin);
106
+ --_border-color: var(--_form-theme);
107
+ --_outline-width: var(--input-outline-width-thin);
108
+
109
+ &.theme-secondary {
110
+ --_form-theme: var(--theme-form-secondary);
111
+ --_focus-colour: var(--theme-form-secondary-focus);
112
+ }
113
+
114
+ &.error {
115
+ --_form-theme: var(--theme-error);
116
+ }
117
+
118
+ .input-textarea-core {
119
+ color: var(--_form-theme);
120
+ background-color: transparent;
121
+ line-height: var(--line-height);
122
+ field-sizing: content;
123
+ min-height: 3rem;
124
+
125
+ &:focus {
126
+ outline: none;
127
+ box-shadow: none;
128
+ border: none;
129
+ }
130
+
131
+ &:-internal-autofill-selected,
132
+ &:autofill {
133
+ background-color: transparent !important;
134
+ }
135
+ }
136
+
137
+ .input-textarea-label {
138
+ color: var(--_form-theme);
139
+ margin: initial;
140
+ line-height: var(--line-height);
141
+ padding: initial;
142
+ transition: color 0.2s ease-in-out;
143
+ }
144
+
145
+ display: grid;
146
+ border-radius: 2px;
147
+ border: var(--_border-width) solid var(--_border-color);
148
+
149
+ margin-bottom: 20px;
150
+ overflow: hidden;
151
+
152
+ &:focus-within {
153
+ --_border-color: white;
154
+ outline: var(--_outline-width) solid hsl(from var(--_form-theme) h s 50%);
155
+ background-color: hsl(from var(--_form-theme) h s 95%);
156
+ }
157
+
158
+ &:has(.input-textarea-core:focus-visible) {
159
+ box-shadow: 0 0 2px 3px var(--_focus-colour);
160
+ outline-color: var(--_focus-colour);
161
+ }
162
+
163
+ &.error {
164
+ /* outline: calc(var(--_border-width) * 2) solid var(--theme-error); */
165
+
166
+ border: var(--_border-width) solid var(--theme-error);
167
+ outline: var(--_outline-width) solid hsl(from var(--theme-error) h s 75%);
168
+
169
+ background-color: hsl(from var(--theme-error) h s 95%);
170
+ }
171
+
172
+ .input-textarea-label {
173
+ grid-row: 1;
174
+ grid-column: 1;
175
+
176
+ font-family: var(--font-family);
177
+ font-size: 20px;
178
+ font-weight: 700;
179
+ padding: var(--_gutter);
180
+ transform: translateY(12px);
181
+ transition: all linear 0.2s;
182
+ background-color: transparent;
183
+ z-index: 2;
184
+ height: 3.5rem;
185
+ transition: color 0.2s ease-in-out;
186
+
187
+ &.active,
188
+ &.dirty,
189
+ &.error {
190
+ font-size: 16px;
191
+ height: 1.5em;
192
+ transform: translateY(-2px);
193
+ z-index: auto;
194
+ }
195
+ }
196
+
197
+ .input-textarea-container {
198
+ display: grid;
199
+ grid-row: 1;
200
+ grid-column: 1;
201
+ margin-top: 2rem;
202
+ background-color: transparent;
203
+ opacity: 0;
204
+ transition: opacity linear 0.2s;
205
+
206
+ &.active,
207
+ &.dirty,
208
+ &.error {
209
+ opacity: 1;
210
+ }
211
+
212
+ .input-textarea-core {
213
+ font-family: var(--font-family);
214
+ border: 0px solid green;
215
+ padding: calc(var(--_gutter) / 2) var(--_gutter);
216
+ font-size: var(--font-size);
217
+ margin: 0;
218
+ /* opacity: 0;
219
+ transition: opacity linear 0.2s;
220
+
221
+ &.active,
222
+ &.dirty {
223
+ opacity: 1;
224
+ } */
225
+ /*
226
+ &::placeholder,
227
+ &:-ms-input-placeholder,
228
+ &::-moz-placeholder, */
229
+ &::-webkit-input-placeholder {
230
+ font-family: var(--font-family);
231
+ /* color: var(--gray-5); */
232
+ color: hsl(from var(--_form-theme) h s 50%);
233
+ font-size: var(--font-size);
234
+ font-style: italic;
235
+ font-weight: 500;
236
+ }
237
+ }
238
+ }
239
+ }
240
+
241
+ /*
242
+ * Compact UI
243
+ **/
244
+
245
+ .input-textarea-material {
246
+ &.compact {
247
+ overflow: initial;
248
+
249
+ &:focus-within {
250
+ background-color: initial;
251
+ }
252
+
253
+ &.error {
254
+ background-color: initial;
255
+ }
256
+ }
257
+
258
+ .input-textarea-label {
259
+ &.compact {
260
+ align-content: center;
261
+ font-size: 16px;
262
+ padding: 0 12px;
263
+ transform: translateY(0);
264
+
265
+ span {
266
+ padding: 0 8px;
267
+ }
268
+
269
+ &.active,
270
+ &.dirty,
271
+ &.error {
272
+ font-size: 16px;
273
+ font-weight: 500;
274
+ transform: translateY(-14px);
275
+ z-index: auto;
276
+
277
+ span {
278
+ background-color: white;
279
+ }
280
+ }
281
+ }
282
+ }
283
+
284
+ .input-textarea-container {
285
+ &.compact {
286
+ margin: 10px 8px 6px 8px;
287
+ }
288
+ }
289
+ }
290
+ </style>
@@ -0,0 +1,85 @@
1
+ <template>
2
+ <div class="ui-content-grid" :class="[applyClasses]" :data-testid="dataTestid">
3
+ <div v-if="hasSlot1" class="col-1">
4
+ <slot name="slot1"></slot>
5
+ </div>
6
+ <div v-if="hasSlot2" class="col-2">
7
+ <slot name="slot2"></slot>
8
+ </div>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ const props = defineProps({
14
+ dataTestid: {
15
+ type: String,
16
+ default: 'ui-content-grid',
17
+ },
18
+ applyClasses: {
19
+ type: String,
20
+ default: '',
21
+ },
22
+ });
23
+
24
+ const slots = useSlots();
25
+ const hasSlot1 = ref(slots.slot1 !== undefined);
26
+ const hasSlot2 = ref(slots.slot2 !== undefined);
27
+ </script>
28
+
29
+ <style lang="css">
30
+ .ui-content-grid {
31
+ --_margin-inline: 0;
32
+ --_grid-template-columns: repeat(4, 1fr);
33
+ --_grid-template-rows: repeat(2, auto);
34
+ --_grid-gap: 16px;
35
+
36
+ display: grid;
37
+ gap: var(--_grid-gap);
38
+ grid-template-columns: var(--_grid-template-columns);
39
+ grid-template-rows: var(--_grid-template-rows);
40
+ margin-inline: var(--_margin-inline);
41
+
42
+ @container content (min-width: 768px) {
43
+ --_margin-inline: 0;
44
+ --_grid-template-columns: repeat(6, 1fr);
45
+ --_grid-gap: 32px;
46
+ }
47
+
48
+ @container content (min-width: 1024px) {
49
+ --_margin-inline: 0;
50
+ --_grid-template-columns: repeat(12, 1fr);
51
+ --_grid-template-rows: initial;
52
+ }
53
+
54
+ .col-1 {
55
+ --_grid-column: 1 / span 4;
56
+ --_grid-row: 1;
57
+ grid-column: var(--_grid-column);
58
+ grid-row: var(--_grid-row);
59
+
60
+ @container content (min-width: 768px) {
61
+ --_grid-column: 1 / span 6;
62
+ }
63
+
64
+ @container content (min-width: 1024px) {
65
+ --_grid-column: 1 / span 6;
66
+ }
67
+ }
68
+
69
+ .col-2 {
70
+ --_grid-column: 1 / span 4;
71
+ --_grid-row: 2;
72
+ grid-column: var(--_grid-column);
73
+ grid-row: var(--_grid-row);
74
+
75
+ @container content (min-width: 768px) {
76
+ --_grid-column: 1 / span 6;
77
+ }
78
+
79
+ @container content (min-width: 1024px) {
80
+ --_grid-column: 7 / span 6;
81
+ --_grid-row: 1;
82
+ }
83
+ }
84
+ }
85
+ </style>
@@ -2,15 +2,17 @@ import type { IFormData } from '@/types/types.forms';
2
2
 
3
3
  export function useErrorMessage(name: string, formData: Ref<IFormData>) {
4
4
  const defaultError = ref('');
5
- const customErrorMessages = ref(toRaw(formData.value.customErrorMessages));
5
+ const errorMessages = ref(formData.value.errorMessages);
6
6
 
7
7
  const hasCustomError = () => {
8
- return customErrorMessages.value[name] !== undefined && customErrorMessages.value[name].useCustomError;
8
+ return errorMessages.value[name] !== undefined && errorMessages.value[name].useCustomError;
9
9
  };
10
10
 
11
11
  const errorMessage = computed(() => {
12
+ console.log(`errorMessage()`);
12
13
  if (hasCustomError()) {
13
- return customErrorMessages.value[name].message;
14
+ console.log(`errorMessage() | IF`);
15
+ return errorMessages.value[name].message;
14
16
  } else {
15
17
  return defaultError.value;
16
18
  }
@@ -21,20 +23,30 @@ export function useErrorMessage(name: string, formData: Ref<IFormData>) {
21
23
  };
22
24
 
23
25
  const fieldHasError = computed(() => {
26
+ // console.log(`fieldHasError() | name(${name})`);
27
+ nextTick();
24
28
  if (formData.value.submitDisabled) {
29
+ console.log(`fieldHasError() | name(${name}) | IF`);
25
30
  if (hasCustomError()) {
31
+ console.log(`fieldHasError() | name(${name}) | IF | IF`);
32
+
26
33
  return true;
27
34
  } else if (Object.keys(formData.value.validityState).length > 0 && formData.value.validityState[name] !== undefined) {
35
+ console.log(`fieldHasError() | name(${name}) | IF | ELSE IF`);
36
+
28
37
  return !formData.value.validityState[name];
29
38
  }
39
+ console.log(`fieldHasError() | name(${name}) | IF | ELSE`);
40
+
30
41
  return false;
31
42
  }
32
43
  });
33
44
 
34
45
  const removeCustomError = (valid: boolean = false) => {
35
- formData.value.validityState[name] = valid;
46
+ console.log(`useErrorMessage | removeCustomError | name(${name}) | valid(${valid})`);
47
+ // formData.value.validityState[name] = valid;
36
48
  // await nextTick();
37
- delete formData.value.customErrorMessages[name];
49
+ // delete formData.value.errorMessages[name];
38
50
  };
39
51
 
40
52
  return {
@@ -1,6 +1,8 @@
1
- import type { IFormData, IFieldsInitialState, ICustomErrorMessage, ICustomErrorMessagesArr } from '@/types/types.forms';
1
+ import type { IFormData, IFieldsInitialState, IFormFieldC12, IApiErrorMessages, ICustomErrorMessage, IErrorMessagesArr } from '@/types/types.forms';
2
+ import { formFieldC12 } from '@/components/forms/c12/utils';
2
3
 
3
- export function useFormControl(fieldsInitialState: IFieldsInitialState | Ref<IFieldsInitialState | null>) {
4
+ // export function useFormControl(name: string = '') {
5
+ export function useFormControl(name: string = '') {
4
6
  let savedInitialState = {};
5
7
 
6
8
  const formData = ref<IFormData>({
@@ -10,24 +12,27 @@ export function useFormControl(fieldsInitialState: IFieldsInitialState | Ref<IFi
10
12
  focusedField: '',
11
13
  isPending: false,
12
14
  errorCount: 0,
13
- customErrorMessages: {},
15
+ errorMessages: {},
16
+ formFieldsC12: {},
14
17
  hasCustomErrorMessages: false,
15
18
  formIsValid: false,
16
- submitSuccess: false,
19
+ submitAttempted: false,
17
20
  submitDisabled: false,
21
+ submitSuccess: false,
22
+ displayErrorMessages: false,
18
23
  });
19
24
 
20
- const initValidationState = async () => {
25
+ const initValidationState = async (fieldsInitialState: IFieldsInitialState | Ref<IFieldsInitialState | null>) => {
21
26
  const fields = Object.keys(fieldsInitialState.value || {});
22
- const state = fields.reduce((acc, field) => {
23
- acc[field] = false;
24
- return acc;
27
+ const state = fields.reduce((accumulatedFields, field) => {
28
+ accumulatedFields[field] = false;
29
+ return accumulatedFields;
25
30
  }, {} as Record<string, boolean>);
26
31
  formData.value.validityState = state;
27
32
  };
28
33
 
29
- const initFormData = async () => {
30
- await initValidationState();
34
+ const initFormData = async (fieldsInitialState: IFieldsInitialState | Ref<IFieldsInitialState | null>) => {
35
+ initValidationState(fieldsInitialState);
31
36
 
32
37
  if (fieldsInitialState !== null) {
33
38
  savedInitialState = toRaw(fieldsInitialState.value) as IFieldsInitialState;
@@ -36,6 +41,17 @@ export function useFormControl(fieldsInitialState: IFieldsInitialState | Ref<IFi
36
41
  return;
37
42
  };
38
43
 
44
+ const initFormFieldsC12 = (name: string, formFieldC12: IFormFieldC12) => {
45
+ formData.value.formFieldsC12[name] = formFieldC12;
46
+ return;
47
+ };
48
+
49
+ const updatePreviousValues = () => {
50
+ Object.keys(formData.value.data).forEach((key) => {
51
+ formData.value.formFieldsC12[key].previousValue = formData.value.data[key];
52
+ });
53
+ };
54
+
39
55
  const getErrorCount = async (updateState: boolean = false) => {
40
56
  await nextTick();
41
57
 
@@ -45,17 +61,26 @@ export function useFormControl(fieldsInitialState: IFieldsInitialState | Ref<IFi
45
61
 
46
62
  if (updateState) {
47
63
  formData.value.submitDisabled = true;
64
+ formData.value.displayErrorMessages = formData.value.errorCount > 0;
65
+ formData.value.submitAttempted = true;
48
66
  }
49
67
 
50
68
  if (formData.value.submitDisabled) {
51
69
  formData.value.submitDisabled = !formData.value.formIsValid;
52
70
  }
53
71
 
72
+ // update fieldHasError ref
73
+ // if (typeof formData.value!.formFieldsC12[name] !== 'undefined') {
74
+ // fieldHasError.value = formData.value!.submitAttempted && !formData.value!.formFieldsC12[name].isValid;
75
+ // } else {
76
+ // fieldHasError.value = false;
77
+ // }
78
+
54
79
  return formData.value.errorCount;
55
80
  };
56
81
 
57
82
  // Function to count items with "useCustomError" set to true
58
- const countItemsWithCustomError = (obj: ICustomErrorMessagesArr) => {
83
+ const countItemsWithCustomError = (obj: IErrorMessagesArr) => {
59
84
  let count = 0;
60
85
 
61
86
  for (const key in obj) {
@@ -70,37 +95,100 @@ export function useFormControl(fieldsInitialState: IFieldsInitialState | Ref<IFi
70
95
  /*
71
96
  * Useage:
72
97
  *
73
- * const { updateCustomErrors } = useFormControl();
98
+ * const { updateErrorMessages } = useFormControl();
74
99
  *
75
100
  * Add/Update entry
76
101
  * const sampleCustomErrorEmail = {
77
102
  * useCustomError: true,
78
103
  * message: "This is a sample custom error for error EMAIL",
79
104
  * };
80
- * updateCustomErrors("email", sampleCustomErrorEmail);
105
+ * updateErrorMessages("email", sampleCustomErrorEmail);
81
106
  */
82
- const updateCustomErrors = (name: string, message: null | string = null, valid: boolean = false) => {
83
- if (message !== null) {
84
- formData.value.validityState[name] = valid;
85
- formData.value.customErrorMessages[name] = {
86
- useCustomError: true,
87
- message,
88
- };
107
+ const updateErrorMessages = async (name: string, message: string = '', valid: boolean = false) => {
108
+ if (!valid) {
109
+ // formData.value.validityState[name] = valid;
110
+ // formData.value.errorMessages[name] = {
111
+ // useCustomError: true,
112
+ // message,
113
+ // };
114
+
115
+ formData.value.formFieldsC12[name].useCustomError = true;
116
+
117
+ // if (typeof message === 'string') {
118
+ // formData.value.formFieldsC12[name].customErrors = message;
119
+ // } else if (typeof message === 'object') {
120
+ // formData.value.formFieldsC12[name].customErrors = message;
121
+ // }
122
+
123
+ formData.value.formFieldsC12[name].customErrors = message;
124
+ formData.value.formFieldsC12[name].isValid = valid;
125
+
126
+ // formData.value.errorMessages[name].useCustomError = true;
127
+ // formData.value.errorMessages[name].message = message;
128
+ }
129
+ formData.value.hasCustomErrorMessages = countItemsWithCustomError(formData.value.errorMessages) > 0;
130
+ };
131
+
132
+ const useApiErrors = async (errors: IApiErrorMessages) => {
133
+ // Object.keys(errors).forEach((key) => {
134
+ // updateErrorMessages(key, errors[key]);
135
+ // });
136
+
137
+ for (const [key, message] of Object.entries(errors)) {
138
+ // console.log(`${key}: ${message}`);
139
+ updateErrorMessages(key, message);
89
140
  }
90
- formData.value.hasCustomErrorMessages = countItemsWithCustomError(formData.value.customErrorMessages) > 0;
91
141
  };
92
142
 
93
- const resetForm = () => {
94
- formData.value.data = toRaw(fieldsInitialState.value) as IFieldsInitialState;
95
- formData.value.validityState = {};
96
- formData.value.errorCount = 0;
97
- formData.value.isPending = false;
98
- formData.value.customErrorMessages = {};
99
- formData.value.formIsValid = false;
143
+ // const resetForm = () => {
144
+ // console.log('resetForm()');
145
+ // formData.value.data = toRaw(fieldsInitialState.value) as IFieldsInitialState;
146
+ // formData.value.validityState = {};
147
+ // formData.value.errorCount = 0;
148
+ // formData.value.isPending = false;
149
+ // formData.value.errorMessages = {};
150
+ // formData.value.formIsValid = false;
151
+ // };
152
+
153
+ const fieldIsDirty = (name: string) => {
154
+ if (typeof formData.value.formFieldsC12[name] !== 'undefined') {
155
+ return formData.value.formFieldsC12[name].isDirty;
156
+ } else {
157
+ return false;
158
+ }
100
159
  };
101
160
 
161
+ // const fieldHasError = (name: string) => {
162
+ // const currentValidityState = formData.value.validityState[name];
163
+
164
+ // if (formData.value.submitAttempted) {
165
+ // return currentValidityState;
166
+ // }
167
+ // return false;
168
+ // };
169
+
170
+ // const fieldHasError = computed({
171
+ // // getter
172
+ // get() {
173
+ // console.log(`fieldHasError getter: ${name}`);
174
+ // if (typeof formData.value!.formFieldsC12[name] !== 'undefined') {
175
+ // return !formData.value!.formFieldsC12[name].isValid;
176
+ // }
177
+ // return formData.value.validityState[name];
178
+ // },
179
+ // // setter
180
+ // set(newValue) {
181
+ // if (formData.value.submitAttempted) {
182
+ // return newValue;
183
+ // }
184
+ // return false;
185
+ // },
186
+ // });
187
+
188
+ // const fieldHasError = ref(false);
189
+
102
190
  const formIsValid = computed(() => {
103
- return formData.value.errorCount === 0;
191
+ return formData.value.formIsValid;
104
192
  });
105
193
 
106
194
  const submitDisabled = computed(() => {
@@ -109,9 +197,12 @@ export function useFormControl(fieldsInitialState: IFieldsInitialState | Ref<IFi
109
197
 
110
198
  // Keep an eye on this for performance issue
111
199
 
112
- watchEffect(() => {
113
- console.log('watchEffect: formData.value', formData.value.validityState);
114
- });
200
+ // const updateFieldValidity = (name: string, valid: boolean) => {
201
+ // console.log(`updateFieldValidity: name:${name} - valid:${valid}`);
202
+ // console.log(formData.value);
203
+ // // formData.value.formFieldsC12[name].isValid = valid;
204
+ // formData.value.validityState[name] = valid;
205
+ // };
115
206
 
116
207
  watch(
117
208
  () => formData.value.validityState,
@@ -121,16 +212,35 @@ export function useFormControl(fieldsInitialState: IFieldsInitialState | Ref<IFi
121
212
  { deep: true }
122
213
  );
123
214
 
124
- onMounted(() => {
125
- initFormData();
126
- });
215
+ watch(
216
+ () => formData.value.formFieldsC12,
217
+ () => {
218
+ formData.value.formFieldsC12;
219
+ },
220
+ { deep: true }
221
+ );
222
+
223
+ watch(
224
+ () => formData.value.isPending,
225
+ (newValue, oldValue) => {
226
+ if (newValue) {
227
+ updatePreviousValues();
228
+ }
229
+ }
230
+ );
127
231
 
128
232
  return {
129
233
  formData,
234
+ initFormData,
235
+ initFormFieldsC12,
130
236
  getErrorCount,
131
- updateCustomErrors,
132
- resetForm,
237
+ updateErrorMessages,
238
+ // resetForm,
133
239
  formIsValid,
134
240
  submitDisabled,
241
+ useApiErrors,
242
+ // fieldHasError,
243
+ fieldIsDirty,
244
+ // updateFieldValidity,
135
245
  };
136
246
  }