PluginProbe
The Innovative Form Builder – IvyForms / 0.8
The Innovative Form Builder – IvyForms v0.8
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / views / public / fields / NumberFormField.vue

NumberFormField.vue in The Innovative Form Builder – IvyForms 0.8, at frontend/src/views/public/fields/NumberFormField.vue

118 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <div
3 :class="[
4 'ivyforms-field',
5 'ivyforms-field__number',
6 'ivyforms-field__number_' + field.id,
7 field.cssClasses,
8 { 'is-readonly': field.readOnly },
9 ]"
10 >
11 <IvyFormItem
12 :label="field.hideLabel ? '' : field.label"
13 :required="field.required"
14 :error="error"
15 :prop="field.type + '_' + field.fieldIndex"
16 :show-info="!!field.description"
17 :info-text="field.description || ''"
18 :show-info-icon="false"
19 :label-position="field.labelPosition"
20 >
21 <IvyTextNumberInput
22 :id="fieldID"
23 v-model="localModelValue"
24 :aria-label="field.label"
25 class="ivyforms-field__number-input"
26 :placeholder="field.placeholder"
27 :disabled="disabled"
28 :readonly="props.field.readOnly"
29 :required="field.required"
30 :step="field.step && field.step > 0 ? field.step : 1"
31 :number-format="field.numberFormat || ''"
32 />
33 </IvyFormItem>
34 </div>
35 </template>
36
37 <script setup lang="ts">
38 import { computed, inject } from 'vue'
39 import IvyTextNumberInput from '@/views/_components/input/IvyTextNumberInput.vue'
40
41 interface Field {
42 id: number
43 formId: number
44 fieldIndex: number
45 type: string
46 label: string
47 placeholder?: string
48 required?: boolean
49 hideLabel?: boolean
50 readOnly?: boolean
51 description?: string
52 cssClasses?: string
53 // Added optional numeric input configuration
54 step?: number
55 numberFormat?: 'us_decimal' | 'us_int' | 'eu_decimal' | 'eu_int' | ''
56 labelPosition?: string
57 noDuplicates?: boolean
58 // Any other field properties from your data
59 }
60 interface FieldProps {
61 modelValue: string | number | null | undefined
62 field: Field
63 disabled?: boolean
64 error?: string
65 }
66
67 const props = withDefaults(defineProps<FieldProps>(), {
68 modelValue: '',
69 disabled: false,
70 error: '',
71 })
72
73 const emit = defineEmits(['update:modelValue'])
74
75 // Inject clearFieldError function from parent
76 const clearFieldError = inject<(fieldKey: string) => void>('clearFieldError', () => {})
77
78 // Generate field key for clearing errors
79 const fieldKey = computed(() => {
80 return props.field.type + '_' + props.field.fieldIndex
81 })
82
83 // Handle input event to clear errors when user starts typing
84 const handleInput = (value: string | number | null | undefined) => {
85 emit('update:modelValue', value === undefined || value === null ? '' : value)
86 clearFieldError(fieldKey.value)
87 }
88
89 const localModelValue = computed({
90 get() {
91 const val = props.modelValue
92 if (val === '' || val === null || val === undefined || isNaN(Number(val))) return undefined
93 return typeof val === 'number' ? val : Number(val)
94 },
95 set(value) {
96 handleInput(value)
97 },
98 })
99 // Generate unique field ID as a string
100 const fieldID = computed(() => {
101 return `ivyforms-field__number-input_${props.field.formId || ''}_${props.field.fieldIndex || ''}`
102 })
103 </script>
104
105 <style scoped lang="scss">
106 .ivyforms-field__number {
107 &.is-readonly {
108 :deep(.el-input__wrapper),
109 :deep(.el-input__wrapper:hover),
110 :deep(.el-input__wrapper.is-focus),
111 :deep(.el-input__inner) {
112 cursor: not-allowed;
113 pointer-events: none;
114 }
115 }
116 }
117 </style>
118